2
0

Compare commits

..

33 Commits

Author SHA1 Message Date
84c7d728c5 modified: ../../../main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java
modified:   ../../resources/bytecode/javFiles/Faculty.jav
	modified:   ../../resources/bytecode/javFiles/MatrixOP.jav
2019-04-26 12:03:57 +02:00
73f412d22d Klassendatei fuer FunN beim Methodaufruf wird erzeugt, wenn der Receiver
den Typ FunN besitzt.
Die Loesung vom Duplicate Field Problem wird angepasst.
2019-04-26 11:56:58 +02:00
9ffc74467b Wenn ein Attribut mehrere Loesungen bekommt, wird die Bytecodeerzeugung
abgebrochen und ensprechende Exception geworfen.
2019-04-26 10:27:15 +02:00
5950fcc0a9 Neue Klasse MethodCallHelper und Exceptions definiert, die fuer die
Uebersetzung von MethodCalls verwendet werden
2019-04-24 15:43:00 +02:00
d2fb17ad4e Merge branch 'bcGenerics' of ssh://gohorb.ba-horb.de/bahome/projekt/git/JavaCompilerCore into bcGenerics 2019-04-21 22:32:20 +02:00
d9f084cd0f modified: ../../bytecode/javFiles/Faculty.jav
neue Imports hinzugefuegt
2019-04-21 22:31:55 +02:00
6a519ff6dc Ein Feld wird nur einmal in Bytecode uebersetzt. genIns in ResultSet
wird angepasst.
2019-04-18 13:17:50 +02:00
5b527ec8ab Merge branch 'bcGenerics' of ssh://abualia@gohorb.ba-horb.de/bahome/projekt/git/JavaCompilerCore into bcGenerics 2019-04-18 10:50:02 +02:00
709041f024 Adapted TypedID jav-file 2019-04-18 10:48:59 +02:00
e086ff187e modified: ../../../../main/java/de/dhbwstuttgart/typeinference/result/ResolvedType.java
Attribut additionalGenerics auskommentiert.
2019-04-12 10:41:42 +02:00
588212389a Die Bestimmung der Constraints aus dem ResolvedType herausgenommen und im ResultSet integriert.
Damit kommen immer die gleichen Constraints raus. Diese werden ohnehin in der Bytecodegenerierung
nochmals ausgewertet.

	modified:   ../../../../main/java/de/dhbwstuttgart/bytecode/TPHExtractor.java
Zugriff auf Constraints ueber ResultSet eingefuehrt

	modified:   ../../../../main/java/de/dhbwstuttgart/bytecode/signature/Signature.java
Zugriff auf Constraints ueber ResultSet eingefuehrt

	modified:   ../../../../main/java/de/dhbwstuttgart/core/JavaTXCompiler.java
	modified:   ../../../../main/java/de/dhbwstuttgart/typeinference/result/GenericInsertPair.java
	modified:   ../../../../main/java/de/dhbwstuttgart/typeinference/result/PairTPHequalRefTypeOrWildcardType.java
	modified:   ../../../../main/java/de/dhbwstuttgart/typeinference/result/PairTPHsmallerTPH.java
toString veraendert

	modified:   ../../../../main/java/de/dhbwstuttgart/typeinference/result/ResultSet.java
Attribut genIns eingefuehrt, indem alle GenericInsertPairs gespeichert werden, die Form (TPH a <. TPH b)
im Attribut results haben

	modified:   ../../../../main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java
	modified:   ../../bytecode/javFiles/Id.jav
	modified:   ../../bytecode/javFiles/MatrixOP.jav
2019-04-12 10:28:39 +02:00
1454281628 Merge branch 'bigRefactoring' of ssh://gohorb.ba-horb.de/bahome/projekt/git/JavaCompilerCore into bcGenerics 2019-04-11 11:57:30 +02:00
602216d9e2 Generics beruecksichtigt 2019-04-11 11:26:54 +02:00
e53c29f582 modified: ../../../main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java
Typeinference-Exception eingefuegt, wenn kein korrekter Typ inferierbar ist.

	modified:   ../../resources/bytecode/javFiles/Id.jav
2019-04-06 00:53:35 +02:00
656c77d16b Merge branch 'bytecode2' of ssh://gohorb.ba-horb.de/bahome/projekt/git/JavaCompilerCore into bigRefactoring 2019-04-05 12:52:28 +02:00
9d16855ce2 Bug in Matrix gefixt 2019-04-05 12:38:29 +02:00
9d2fdf9692 Merge branch 'bytecode2' of ssh://abualia@gohorb.ba-horb.de/bahome/projekt/git/JavaCompilerCore into bytecode2 2019-04-05 12:06:22 +02:00
5c5b1ea2b1 IdTest funktioniert 2019-04-05 12:05:07 +02:00
2e2227b701 Merge branch 'bytecode2' of ssh://gohorb.ba-horb.de/bahome/projekt/git/JavaCompilerCore into bytecode2 2019-04-05 12:00:30 +02:00
16baa5eaa8 modified: ../../../../main/java/de/dhbwstuttgart/syntaxtree/factory/UnifyTypeFactory.java
modified:   ../../../../main/java/de/dhbwstuttgart/typeinference/unify/model/ReferenceType.java

Konstruktur fuer ReferenceType mit zwei Argumenten versehen, um Generice unterscheiden zu können.
2019-04-05 11:59:34 +02:00
588b9ef83a Merge branch 'bytecode2' of ssh://abualia@gohorb.ba-horb.de/bahome/projekt/git/JavaCompilerCore into bytecode2 2019-04-05 10:44:52 +02:00
ee932892c6 subString durch contains ersetzt 2019-04-05 10:43:09 +02:00
547ad9601a Merge branch 'bytecode2' of ssh://gohorb.ba-horb.de/bahome/projekt/git/JavaCompilerCore into bytecode2 2019-04-04 14:08:31 +02:00
6c94404f27 [MINOR]: Optimized imports. 2019-03-31 11:45:49 +02:00
2b5b677682 Für Eclipse-Plugin: Vorläufige Lösung zum Einsetzen von Generics nur an Klassen ausgeschaltet. 2019-03-31 11:39:57 +02:00
1edc023ed9 modified: ../../../main/java/de/dhbwstuttgart/syntaxtree/factory/UnifyTypeFactory.java
modified:   ../../../main/java/de/dhbwstuttgart/typeinference/unify/model/ReferenceType.java
Generische Typvariablen im Unify durch Tag im ReferenceType eingefuehrt
2019-03-28 17:44:42 +01:00
df0f26c021 :w:wq 2019-03-28 16:55:48 +01:00
53d1f20a40 Merge remote-tracking branch 'origin/bytecode2' into bytecode2 2019-03-28 14:56:47 +01:00
ec4defd087 Getter and setter for token. 2019-03-28 14:56:36 +01:00
6a2a8313e6 Generics werden in Signature richtig dargestellt und die passende
Deskriptoren werden richtig erzeugt
2019-03-28 14:07:04 +01:00
d4a59517d3 Wenn die Klasse keine Generics besitzt und Methoden besitzen Generics
wird eine new SimplifyResult Instanz erzeugt, da sonst eine
NullException aufgelöst wird
2019-03-21 12:23:50 +01:00
f4b5124fd3 Merge branch 'bytecode2' of ssh://abualia@gohorb.ba-horb.de/bahome/projekt/git/JavaCompilerCore into bytecode2 2019-03-21 12:06:01 +01:00
c921330b55 Methode getSimplifyList definiert, die eine Liste von Ergebnisse des
Simplify-Alg zurueckliefert
2019-03-21 12:03:13 +01:00
40 changed files with 1224 additions and 1419 deletions

Binary file not shown.

@ -7,7 +7,7 @@ http://maven.apache.org/maven-v4_0_0.xsd">
<artifactId>JavaTXcompiler</artifactId>
<packaging>jar</packaging>
<version>0.1</version>
<version>0.2</version>
<name>JavaTXcompiler</name>
<url>http://maven.apache.org</url>
<dependencies>
@ -127,7 +127,7 @@ http://maven.apache.org/maven-v4_0_0.xsd">
<!-- specify your depencies here -->
<!-- groupId:artifactId:version -->
<artifact>
<id>de.dhbwstuttgart:JavaTXcompiler:0.1</id>
<id>de.dhbwstuttgart:JavaTXcompiler:0.2</id>
</artifact>
<artifact>
<id>org.reflections:reflections:0.9.11</id>

@ -1,929 +0,0 @@
package de.dhbwstuttgart.typeinference.unify;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.RecursiveTask;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typeinference.unify.interfaces.IRuleSet;
import de.dhbwstuttgart.typeinference.unify.interfaces.ISetOperations;
import de.dhbwstuttgart.typeinference.unify.interfaces.IUnify;
import de.dhbwstuttgart.typeinference.unify.model.ExtendsType;
import de.dhbwstuttgart.typeinference.unify.model.PairOperator;
import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType;
import de.dhbwstuttgart.typeinference.unify.model.SuperType;
import de.dhbwstuttgart.typeinference.unify.model.TypeParams;
import de.dhbwstuttgart.typeinference.unify.model.Unifier;
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;
import de.dhbwstuttgart.typeinference.unify.model.UnifyType;
import de.dhbwstuttgart.typeinference.unify.model.OrderingUnifyPair;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import com.google.common.collect.Ordering;
/**
* Implementation of the type unification algorithm
* @author Florian Steurer
*/
public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
private static final long serialVersionUID = 1L;
private static int i = 0;
private boolean printtag = false;
public static final String rootDirectory = System.getProperty("user.dir")+"/test/logFiles/";
FileWriter logFile;
/**
* The implementation of setOps that will be used during the unification
*/
protected ISetOperations setOps = new GuavaSetOperations();
/**
* The implementation of the standard unify that will be used during the unification
*/
protected IUnify stdUnify = new MartelliMontanariUnify();
/**
* The implementation of the rules that will be used during the unification.
*/
protected IRuleSet rules;
protected Set<UnifyPair> eq;
protected IFiniteClosure fc;
protected Ordering<Set<UnifyPair>> oup;
protected boolean parallel;
public TypeUnifyTask() {
rules = new RuleSet();
}
public TypeUnifyTask(Set<UnifyPair> eq, IFiniteClosure fc, boolean parallel, FileWriter logFile) {
this.eq = eq;
this.fc = fc;
this.oup = new OrderingUnifyPair(fc);
this.parallel = parallel;
this.logFile = logFile;
rules = new RuleSet(logFile);
}
@Override
protected Set<Set<UnifyPair>> compute() {
return unify(eq, fc, parallel);
}
/**
* Computes all principal type unifiers for a set of constraints.
* @param eq The set of constraints
* @param fc The finite closure
* @return The set of all principal type unifiers
*/
protected Set<Set<UnifyPair>> unify(Set<UnifyPair> eq, IFiniteClosure fc, boolean parallel) {
/*
* Step 1: Repeated application of reduce, adapt, erase, swap
*/
writeLog("Unifikation: " + eq.toString());
eq = eq.stream().map(x -> {x.setVariance((byte)-1); return x;}).collect(Collectors.toCollection(HashSet::new));
Set<UnifyPair> eq0 = applyTypeUnificationRules(eq, fc);
/*
* Step 2 and 3: Create a subset eq1s of pairs where both sides are TPH and eq2s of the other pairs
*/
Set<UnifyPair> eq1s = new HashSet<>();
Set<UnifyPair> eq2s = new HashSet<>();
splitEq(eq0, eq1s, eq2s);
/*
* Step 4: Create possible typings
*
* "Manche Autoren identifizieren die Paare (a, (b,c)) und ((a,b),c)
* mit dem geordneten Tripel (a,b,c), wodurch das kartesische Produkt auch assoziativ wird." - Wikipedia
*/
// There are up to 10 toplevel set. 8 of 10 are the result of the
// cartesian product of the sets created by pattern matching.
List<Set<Set<UnifyPair>>> topLevelSets = new ArrayList<>();
//System.out.println(eq2s);
if(eq1s.size() != 0) { // Do not add empty sets or the cartesian product will always be empty.
Set<Set<UnifyPair>> wrap = new HashSet<>();
wrap.add(eq1s);
topLevelSets.add(wrap); // Add Eq1'
}
// Add the set of [a =. Theta | (a=. Theta) in Eq2']
Set<UnifyPair> bufferSet = eq2s.stream()
.filter(x -> x.getPairOp() == PairOperator.EQUALSDOT && x.getLhsType() instanceof PlaceholderType)
.collect(Collectors.toSet());
if(bufferSet.size() != 0) { // Do not add empty sets or the cartesian product will always be empty.
Set<Set<UnifyPair>> wrap = new HashSet<>();
wrap.add(bufferSet);
topLevelSets.add(wrap);
eq2s.removeAll(bufferSet);
}
// Sets that originate from pair pattern matching
// Sets of the "second level"
Set<UnifyPair> undefinedPairs = new HashSet<>();
if (printtag) System.out.println("eq2s " + eq2s);
//writeLog("BufferSet: " + bufferSet.toString()+"\n");
Set<Set<Set<Set<UnifyPair>>>> secondLevelSets = calculatePairSets(eq2s, fc, undefinedPairs);
//PL 2017-09-20: Im calculatePairSets wird möglicherweise O .< java.lang.Integer
//nicht ausgewertet Faculty Beispiel im 1. Schritt
//PL 2017-10-03 geloest, muesste noch mit FCs mit kleineren
//Typen getestet werden.
if (printtag) System.out.println("secondLevelSets:" +secondLevelSets);
// If pairs occured that did not match one of the cartesian product cases,
// those pairs are contradictory and the unification is impossible.
if(!undefinedPairs.isEmpty()) {
writeLog("UndefinedPairs; " + undefinedPairs);
Set<Set<UnifyPair>> error = new HashSet<>();
error.add(undefinedPairs);
return error;
}
/* Up to here, no cartesian products are calculated.
* filters for pairs and sets can be applied here */
// Alternative: Sub cartesian products of the second level (pattern matched) sets
// "the big (x)"
/* for(Set<Set<Set<UnifyPair>>> secondLevelSet : secondLevelSets) {
//System.out.println("secondLevelSet "+secondLevelSet.size());
List<Set<Set<UnifyPair>>> secondLevelSetList = new ArrayList<>(secondLevelSet);
Set<List<Set<UnifyPair>>> cartResult = setOps.cartesianProduct(secondLevelSetList);
//System.out.println("CardResult: "+cartResult.size());
// Flatten and add to top level sets
Set<Set<UnifyPair>> flat = new HashSet<>();
int j = 0;
for(List<Set<UnifyPair>> s : cartResult) {
j++;
//System.out.println("s from CardResult: "+cartResult.size() + " " + j);
Set<UnifyPair> flat1 = new HashSet<>();
for(Set<UnifyPair> s1 : s)
flat1.addAll(s1);
flat.add(flat1);
}
//topLevelSets.add(flat);
}
*/
//Alternative KEIN KARTESISCHES PRODUKT der secondlevel Ebene bilden
for(Set<Set<Set<UnifyPair>>> secondLevelSet : secondLevelSets) {
for (Set<Set<UnifyPair>> secondlevelelem : secondLevelSet) {
topLevelSets.add(secondlevelelem);
}
}
//System.out.println(topLevelSets);
//System.out.println();
//Aufruf von computeCartesianRecursive ANFANG
return computeCartesianRecursive(new HashSet<>(), new ArrayList<>(topLevelSets), eq, fc, parallel);
}
Set<Set<UnifyPair>> unify2(Set<Set<UnifyPair>> setToFlatten, Set<UnifyPair> eq, IFiniteClosure fc, boolean parallel) {
//Aufruf von computeCartesianRecursive ENDE
//keine Ahnung woher das kommt
//Set<Set<UnifyPair>> setToFlatten = topLevelSets.stream().map(x -> x.iterator().next()).collect(Collectors.toCollection(HashSet::new));
//Muss auskommentiert werden, wenn computeCartesianRecursive ANFANG
// Cartesian product over all (up to 10) top level sets
//Set<Set<Set<UnifyPair>>> eqPrimeSet = setOps.cartesianProduct(topLevelSets)
// .stream().map(x -> new HashSet<>(x))
// .collect(Collectors.toCollection(HashSet::new));
//Muss auskommentiert werden, wenn computeCartesianRecursive ENDE
Set<Set<UnifyPair>> eqPrimePrimeSet = new HashSet<>();
Set<TypeUnifyTask> forks = new HashSet<>();
//Muss auskommentiert werden, wenn computeCartesianRecursive ANFANG
//for(Set<Set<UnifyPair>> setToFlatten : eqPrimeSet) {
// Flatten the cartesian product
//Muss auskommentiert werden, wenn computeCartesianRecursive ENDE
Set<UnifyPair> eqPrime = new HashSet<>();
setToFlatten.stream().forEach(x -> eqPrime.addAll(x));
/*
* Step 5: Substitution
*/
//System.out.println("vor Subst: " + eqPrime);
Optional<Set<UnifyPair>> eqPrimePrime = rules.subst(eqPrime);
/*
* Step 6 a) Restart (fork) for pairs where subst was applied
*/
if(parallel) {
if (eqPrime.equals(eq)) //PL 2017-09-29 auskommentiert und durch
//(!eqPrimePrime.isPresent()) //PL 2071-09-29 dies ersetzt
//Begruendung: Wenn in der Substitution keine Veraenderung
//(!eqPrimePrime.isPresent()) erfolgt ist, ist das Ergebnis erzielt.
eqPrimePrimeSet.add(eqPrime);
else if(eqPrimePrime.isPresent()) {
//System.out.println("nextStep: " + eqPrimePrime.get());
TypeUnifyTask fork = new TypeUnifyTask(eqPrimePrime.get(), fc, true, logFile);
forks.add(fork);
fork.fork();
}
else {
//System.out.println("nextStep: " + eqPrime);
TypeUnifyTask fork = new TypeUnifyTask(eqPrime, fc, true, logFile);
forks.add(fork);
fork.fork();
}
}
else { // sequentiell (Step 6b is included)
if (printtag) System.out.println("nextStep: " + eqPrimePrime);
if (eqPrime.equals(eq)) { //PL 2017-09-29 auskommentiert und durch
//(!eqPrimePrime.isPresent()) //PL 2071-09-29 dies ersetzt
//Begruendung: Wenn in der Substitution keine Veraenderung
//(!eqPrimePrime.isPresent()) erfolgt ist, ist das Ergebnis erzielt.
try {
if (isSolvedForm(eqPrime)) {
logFile.write(eqPrime.toString()+"\n");
logFile.flush();
}
}
catch (IOException e) { }
eqPrimePrimeSet.add(eqPrime);
}
else if(eqPrimePrime.isPresent()) {
Set<Set<UnifyPair>> unifyres = unify(eqPrimePrime.get(), fc, false);
eqPrimePrimeSet.addAll(unifyres);
}
else {
Set<Set<UnifyPair>> unifyres = unify(eqPrime, fc, false);
eqPrimePrimeSet.addAll(unifyres);
}
}
//Muss auskommentiert werden, wenn computeCartesianRecursive ANFANG
//}
//Muss auskommentiert werden, wenn computeCartesianRecursive ENDE
/*
* Step 6 b) Build the union over everything.
*/
if(parallel)
for(TypeUnifyTask fork : forks)
eqPrimePrimeSet.addAll(fork.join());
/*
* Step 7: Filter empty sets;
*/
eqPrimePrimeSet = eqPrimePrimeSet.stream().filter(x -> isSolvedForm(x)).collect(Collectors.toCollection(HashSet::new));
if (!eqPrimePrimeSet.isEmpty())
writeLog("Result " + eqPrimePrimeSet.toString());
return eqPrimePrimeSet;
}
Set<Set<UnifyPair>> computeCartesianRecursive(Set<Set<UnifyPair>> fstElems, ArrayList<Set<Set<UnifyPair>>> topLevelSets, Set<UnifyPair> eq, IFiniteClosure fc, boolean parallel) {
ArrayList<Set<Set<UnifyPair>>> remainingSets = new ArrayList<>(topLevelSets);
Set<Set<UnifyPair>> nextSet = remainingSets.remove(0);
ArrayList<Set<UnifyPair>> nextSetasList = new ArrayList<>(nextSet);
Set<Set<UnifyPair>> result = new HashSet<>();
int i = 0;
byte variance = nextSetasList.iterator().next().iterator().next().getVariance();
Set<UnifyPair> a_next = null;
if (nextSetasList.iterator().next().iterator().next().getLhsType().getName().equals("D"))
System.out.print("");
if (nextSetasList.size()>1) {
if (variance == 1) {
a_next = oup.max(nextSetasList.iterator());
}
else if (variance == -1) {
a_next = oup.min(nextSetasList.iterator());
}
else if (variance == 0) {
a_next = nextSetasList.iterator().next();
}
}
else {
a_next = nextSetasList.iterator().next();
}
while (nextSetasList.size() != 0) {
Set<UnifyPair> a = a_next;
//writeLog("nextSet: " + nextSetasList.toString()+ "\n");
nextSetasList.remove(a);
if (nextSetasList.size() > 0) {
if (nextSetasList.size()>1) {
if (variance == 1) {
a_next = oup.max(nextSetasList.iterator());
}
else if (variance == -1) {
a_next = oup.min(nextSetasList.iterator());
}
else {
a_next = nextSetasList.iterator().next();
}
}
else {
a_next = nextSetasList.iterator().next();
}
}
//PL 2018-03-01
//TODO: 1. Maximum und Minimum unterscheiden
//TODO: 2. compare noch für alle Elmemente die nicht X =. ty sind erweitern
//for(Set<UnifyPair> a : newSet) {
i++;
Set<Set<UnifyPair>> elems = new HashSet<Set<UnifyPair>>(fstElems);
elems.add(a);
if (remainingSets.isEmpty()) {
result.addAll(unify2(elems, eq, fc, parallel));
System.out.println("");
}
else {
result.addAll(computeCartesianRecursive(elems, remainingSets, eq, fc, parallel));
}
if (!result.isEmpty()) {
if (variance == 1) {
if (a.iterator().next().getLhsType().getName().equals("WL"))
System.out.print("");
if (a.equals(a_next) ||
(oup.compare(a, a_next) == 1)) {
System.out.print("");
break;
}
else {
System.out.print("");
}
}
else { if (variance == -1) {
if (a.iterator().next().getLhsType().getName().equals("A"))
System.out.print("");
if (a.equals(a_next) || (oup.compare(a, a_next) == -1)) {
System.out.print("");
break;
}
else {
System.out.print("");
}
}
else if (variance == 0) {
break;
}
}
}
}
return result;
}
protected boolean isUndefinedPairSet(Set<Set<UnifyPair>> s) {
boolean res = true;
if (s.size() ==1) {
s.iterator().next().stream().forEach(x -> { res = res && x.isUndefinedPair(); return; });
return res;
}
}
/**
* Checks whether a set of pairs is in solved form.
* @param eqPrimePrime The set of pair
* @return True if in solved form, false otherwise.
*/
protected boolean isSolvedForm(Set<UnifyPair> eqPrimePrime) {
for(UnifyPair pair : eqPrimePrime) {
UnifyType lhsType = pair.getLhsType();
UnifyType rhsType = pair.getRhsType();
if(!(lhsType instanceof PlaceholderType))
return false;
// If operator is not equals, both sides must be placeholders
if(pair.getPairOp() != PairOperator.EQUALSDOT && !(rhsType instanceof PlaceholderType))
return false;
}
return true;
}
/**
* Repeatedly applies type unification rules to a set of equations.
* This is step one of the unification algorithm.
* @return The set of pairs that results from repeated application of the inference rules.
*/
public Set<UnifyPair> applyTypeUnificationRules(Set<UnifyPair> eq, IFiniteClosure fc) {
/*
* Rule Application Strategy:
*
* 1. Swap all pairs and erase all erasable pairs
* 2. Apply all possible rules to a single pair, then move it to the result set.
* Iterating over pairs first, then iterating over rules prevents the application
* of rules to a "finished" pair over and over.
* 2.1 Apply all rules repeatedly except for erase rules. If
* the application of a rule creates new pairs, check immediately
* against the erase rules.
*/
LinkedHashSet<UnifyPair> targetSet = new LinkedHashSet<UnifyPair>();
LinkedList<UnifyPair> eqQueue = new LinkedList<>();
/*
* Swap all pairs and erase all erasable pairs
*/
eq.forEach(x -> swapAddOrErase(x, fc, eqQueue));
/*
* Apply rules until the queue is empty
*/
while(!eqQueue.isEmpty()) {
UnifyPair pair = eqQueue.pollFirst();
// ReduceUp, ReduceLow, ReduceUpLow
Optional<UnifyPair> opt = rules.reduceUpLow(pair);
opt = opt.isPresent() ? opt : rules.reduceLow(pair);
opt = opt.isPresent() ? opt : rules.reduceUp(pair);
opt = opt.isPresent() ? opt : rules.reduceWildcardLow(pair);
opt = opt.isPresent() ? opt : rules.reduceWildcardLowRight(pair);
opt = opt.isPresent() ? opt : rules.reduceWildcardUp(pair);
opt = opt.isPresent() ? opt : rules.reduceWildcardUpRight(pair);
//PL 2018-03-06 auskommentiert muesste falsch sein vgl. JAVA_BSP/Wildcard6.java
//opt = opt.isPresent() ? opt : rules.reduceWildcardLowUp(pair);
//opt = opt.isPresent() ? opt : rules.reduceWildcardUpLow(pair);
//opt = opt.isPresent() ? opt : rules.reduceWildcardLeft(pair);
// Reduce TPH
opt = opt.isPresent() ? opt : rules.reduceTph(pair);
// One of the rules has been applied
if(opt.isPresent()) {
swapAddOrErase(opt.get(), fc, eqQueue);
continue;
}
// Reduce1, Reduce2, ReduceExt, ReduceSup, ReduceEq
//try {
// logFile.write("PAIR1 " + pair + "\n");
// logFile.flush();
//}
//catch (IOException e) { }
Optional<Set<UnifyPair>> optSet = rules.reduce1(pair, fc);
optSet = optSet.isPresent() ? optSet : rules.reduce2(pair);
optSet = optSet.isPresent() ? optSet : rules.reduceExt(pair, fc);
optSet = optSet.isPresent() ? optSet : rules.reduceSup(pair, fc);
optSet = optSet.isPresent() ? optSet : rules.reduceEq(pair);
// ReduceTphExt, ReduceTphSup
optSet = optSet.isPresent() ? optSet : rules.reduceTphExt(pair);
optSet = optSet.isPresent() ? optSet : rules.reduceTphSup(pair);
// FunN Rules
optSet = optSet.isPresent() ? optSet : rules.reduceFunN(pair);
optSet = optSet.isPresent() ? optSet : rules.greaterFunN(pair);
optSet = optSet.isPresent() ? optSet : rules.smallerFunN(pair);
// One of the rules has been applied
if(optSet.isPresent()) {
optSet.get().forEach(x -> swapAddOrErase(x, fc, eqQueue));
continue;
}
// Adapt, AdaptExt, AdaptSup
//try {
// logFile.write("PAIR2 " + pair + "\n");
// logFile.flush();
//}
//catch (IOException e) { }
opt = rules.adapt(pair, fc);
opt = opt.isPresent() ? opt : rules.adaptExt(pair, fc);
opt = opt.isPresent() ? opt : rules.adaptSup(pair, fc);
// One of the rules has been applied
if(opt.isPresent()) {
swapAddOrErase(opt.get(), fc, eqQueue);
continue;
}
// None of the rules has been applied
targetSet.add(pair);
}
return targetSet;
}
/**
* Applies the rule swap to a pair if possible. Then adds the pair to the set if no erase rule applies.
* If an erase rule applies, the pair is not added (erased).
* @param pair The pair to swap and add or erase.
* @param collection The collection to which the pairs are added.
*/
protected void swapAddOrErase(UnifyPair pair, IFiniteClosure fc, Collection<UnifyPair> collection) {
Optional<UnifyPair> opt = rules.swap(pair);
UnifyPair pair2 = opt.isPresent() ? opt.get() : pair;
if(rules.erase1(pair2, fc) || rules.erase3(pair2) || rules.erase2(pair2, fc))
return;
collection.add(pair2);
}
/**
* Splits the equation eq into a set eq1s where both terms are type variables,
* and a set eq2s where one of both terms is not a type variable.
* @param eq Set of pairs to be splitted.
* @param eq1s Subset of eq where both terms are type variables.
* @param eq2s eq/eq1s.
*/
protected void splitEq(Set<UnifyPair> eq, Set<UnifyPair> eq1s, Set<UnifyPair> eq2s) {
for(UnifyPair pair : eq)
if(pair.getLhsType() instanceof PlaceholderType && pair.getRhsType() instanceof PlaceholderType)
eq1s.add(pair);
else
eq2s.add(pair);
}
/**
* Creates sets of pairs specified in the fourth step. Does not calculate cartesian products.
* @param undefined All pairs that did not match one of the 8 cases are added to this set.
* @return The set of the eight cases (without empty sets). Each case is a set, containing sets generated
* from the pairs that matched the case. Each generated set contains singleton sets or sets with few elements
* (as in case 1 where sigma is added to the innermost set).
*/
protected Set<Set<Set<Set<UnifyPair>>>> calculatePairSets(Set<UnifyPair> eq2s, IFiniteClosure fc, Set<UnifyPair> undefined) {
List<Set<Set<Set<UnifyPair>>>> result = new ArrayList<>(8);
// Init all 8 cases
for(int i = 0; i < 8; i++)
result.add(new HashSet<>());
Boolean first = true;
for(UnifyPair pair : eq2s) {
PairOperator pairOp = pair.getPairOp();
UnifyType lhsType = pair.getLhsType();
UnifyType rhsType = pair.getRhsType();
// Case 1: (a <. Theta')
if(pairOp == PairOperator.SMALLERDOT && lhsType instanceof PlaceholderType) {
//System.out.println(pair);
if (first) { //writeLog(pair.toString()+"\n");
Set<Set<UnifyPair>> x1 = unifyCase1((PlaceholderType) pair.getLhsType(), pair.getRhsType(), (byte)1, fc);
//System.out.println(x1);
result.get(0).add(x1);
}
else {
Set<UnifyPair> s1 = new HashSet<>();
s1.add(pair);
Set<Set<UnifyPair>> s2 = new HashSet<>();
s2.add(s1);
result.get(0).add(s2);
}
}
// Case 2: (a <.? ? ext Theta')
else if(pairOp == PairOperator.SMALLERDOTWC && lhsType instanceof PlaceholderType && rhsType instanceof ExtendsType)
if (first) { //writeLog(pair.toString()+"\n");
result.get(1).add(unifyCase2((PlaceholderType) pair.getLhsType(), (ExtendsType) pair.getRhsType(), (byte)0, fc));
}
else {
Set<UnifyPair> s1 = new HashSet<>();
s1.add(pair);
Set<Set<UnifyPair>> s2 = new HashSet<>();
s2.add(s1);
result.get(1).add(s2);
}
// Case 3: (a <.? ? sup Theta')
else if(pairOp == PairOperator.SMALLERDOTWC && lhsType instanceof PlaceholderType && rhsType instanceof SuperType)
if (first) { //writeLog(pair.toString()+"\n");
result.get(2).add(unifyCase3((PlaceholderType) lhsType, (SuperType) rhsType, (byte)0, fc));
}
else {
Set<UnifyPair> s1 = new HashSet<>();
s1.add(pair);
Set<Set<UnifyPair>> s2 = new HashSet<>();
s2.add(s1);
result.get(2).add(s2);
}
// Case 4 was replaced by an inference rule
// Case 4: (a <.? Theta')
//else if(pairOp == PairOperator.SMALLERDOTWC && lhsType instanceof PlaceholderType)
// result.get(3).add(unifyCase4((PlaceholderType) lhsType, rhsType, fc));
// Case 5: (Theta <. a)
else if(pairOp == PairOperator.SMALLERDOT && rhsType instanceof PlaceholderType)
if (first) { //writeLog(pair.toString()+"\n");
if (rhsType.getName().equals("A"))
System.out.println();
result.get(4).add(unifyCase5(lhsType, (PlaceholderType) rhsType, (byte)-1, fc));
}
else {
Set<UnifyPair> s1 = new HashSet<>();
s1.add(pair);
Set<Set<UnifyPair>> s2 = new HashSet<>();
s2.add(s1);
result.get(4).add(s2);
}
// Case 6 was replaced by an inference rule.
// Case 6: (? ext Theta <.? a)
//else if(pairOp == PairOperator.SMALLERDOTWC && lhsType instanceof ExtendsType && rhsType instanceof PlaceholderType)
// result.get(5).add(unifyCase6((ExtendsType) lhsType, (PlaceholderType) rhsType, fc));
// Case 7 was replaced by an inference rule
// Case 7: (? sup Theta <.? a)
//else if(pairOp == PairOperator.SMALLERDOTWC && lhsType instanceof SuperType && rhsType instanceof PlaceholderType)
// result.get(6).add(unifyCase7((SuperType) lhsType, (PlaceholderType) rhsType, fc));
// Case 8: (Theta <.? a)
else if(pairOp == PairOperator.SMALLERDOTWC && rhsType instanceof PlaceholderType)
if (first) { //writeLog(pair.toString()+"\n");
result.get(7).add(
unifyCase8(lhsType, (PlaceholderType) rhsType, (byte)0, fc));
}
else {
Set<UnifyPair> s1 = new HashSet<>();
s1.add(pair);
Set<Set<UnifyPair>> s2 = new HashSet<>();
s2.add(s1);
result.get(7).add(s2);
}
// Case unknown: If a pair fits no other case, then the type unification has failed.
// Through application of the rules, every pair should have one of the above forms.
// Pairs that do not have one of the aboves form are contradictory.
else {
// If a pair is not defined, the unificiation will fail, so the loop can be stopped here.
undefined.add(pair);
break;
}
first = false;
}
// Filter empty sets or sets that only contain an empty set.
return result.stream().map(x -> x.stream().filter(y -> y.size() > 0).collect(Collectors.toCollection(HashSet::new)))
.filter(x -> x.size() > 0).collect(Collectors.toCollection(HashSet::new));
}
/**
* Cartesian product Case 1: (a <. Theta')
*/
protected Set<Set<UnifyPair>> unifyCase1(PlaceholderType a, UnifyType thetaPrime, byte variance, IFiniteClosure fc) {
Set<Set<UnifyPair>> result = new HashSet<>();
boolean allGen = thetaPrime.getTypeParams().size() > 0;
for(UnifyType t : thetaPrime.getTypeParams())
if(!(t instanceof PlaceholderType) || !((PlaceholderType) t).isGenerated()) {
allGen = false;
break;
}
Set<UnifyType> cs = fc.getAllTypesByName(thetaPrime.getName());//cs= [java.util.Vector<NP>, java.util.Vector<java.util.Vector<java.lang.Integer>>, ????java.util.Vector<gen_hv>???]
//PL 18-02-06 entfernt, kommt durch unify wieder rein
//cs.add(thetaPrime);
//PL 18-02-06 entfernt
for(UnifyType c : cs) {
//PL 18-02-05 getChildren durch smaller ersetzt in getChildren werden die Varianlen nicht ersetzt.
Set<UnifyType> thetaQs = fc.smaller(c).stream().collect(Collectors.toCollection(HashSet::new));
//Set<UnifyType> thetaQs = fc.getChildren(c).stream().collect(Collectors.toCollection(HashSet::new));
//thetaQs.add(thetaPrime); //PL 18-02-05 wieder geloescht
//PL 2017-10-03: War auskommentiert habe ich wieder einkommentiert,
//da children offensichtlich ein echtes kleiner und kein kleinergleich ist
//PL 18-02-06: eingefuegt, thetaQs der Form V<V<...>> <. V'<V<...>> werden entfernt
thetaQs = thetaQs.stream().filter(ut -> ut.getTypeParams().arePlaceholders()).collect(Collectors.toCollection(HashSet::new));
//PL 18-02-06: eingefuegt
Set<UnifyType> thetaQPrimes = new HashSet<>();
TypeParams cParams = c.getTypeParams();
if(cParams.size() == 0)
thetaQPrimes.add(c);
else {
ArrayList<Set<UnifyType>> candidateParams = new ArrayList<>();
for(UnifyType param : cParams)
candidateParams.add(fc.grArg(param));
for(TypeParams tp : permuteParams(candidateParams))
thetaQPrimes.add(c.setTypeParams(tp));
}
for(UnifyType tqp : thetaQPrimes) {
//System.out.println(tqp.toString());
//i++;
//System.out.println(i);
//if (i == 62)
// System.out.println(tqp.toString());
Optional<Unifier> opt = stdUnify.unify(tqp, thetaPrime);
if (!opt.isPresent())
continue;
Unifier unifier = opt.get();
unifier.swapPlaceholderSubstitutions(thetaPrime.getTypeParams());
Set<UnifyPair> substitutionSet = new HashSet<>();
for (Entry<PlaceholderType, UnifyType> sigma : unifier)
substitutionSet.add(new UnifyPair(sigma.getKey(), sigma.getValue(), PairOperator.EQUALSDOT));
//List<UnifyType> freshTphs = new ArrayList<>(); PL 18-02-06 in die For-Schleife verschoben
for (UnifyType tq : thetaQs) {
Set<UnifyType> smaller = fc.smaller(unifier.apply(tq));
for(UnifyType theta : smaller) {
List<UnifyType> freshTphs = new ArrayList<>();
Set<UnifyPair> resultPrime = new HashSet<>();
for(int i = 0; !allGen && i < theta.getTypeParams().size(); i++) {
if(freshTphs.size()-1 < i)
freshTphs.add(PlaceholderType.freshPlaceholder());
resultPrime.add(new UnifyPair(freshTphs.get(i), theta.getTypeParams().get(i), PairOperator.SMALLERDOTWC));
}
if(allGen)
resultPrime.add(new UnifyPair(a, theta, PairOperator.EQUALSDOT));
else
resultPrime.add(new UnifyPair(a, theta.setTypeParams(new TypeParams(freshTphs.toArray(new UnifyType[0]))), PairOperator.EQUALSDOT));
resultPrime.addAll(substitutionSet);
//writeLog("Substitution: " + substitutionSet.toString());
resultPrime = resultPrime.stream().map(x -> { x.setVariance(variance); return x;}).collect(Collectors.toCollection(HashSet::new));
result.add(resultPrime);
//writeLog("Result: " + resultPrime.toString());
//writeLog("MAX: " + oup.max(resultPrime.iterator()).toString());
}
}
}
}
return result;
}
/**
* Cartesian Product Case 2: (a <.? ? ext Theta')
*/
private Set<Set<UnifyPair>> unifyCase2(PlaceholderType a, ExtendsType extThetaPrime, byte variance, IFiniteClosure fc) {
Set<Set<UnifyPair>> result = new HashSet<>();
UnifyType aPrime = PlaceholderType.freshPlaceholder();
UnifyType extAPrime = new ExtendsType(aPrime);
UnifyType thetaPrime = extThetaPrime.getExtendedType();
Set<UnifyPair> resultPrime = new HashSet<>();
resultPrime.add(new UnifyPair(a, thetaPrime, PairOperator.SMALLERDOT));
result.add(resultPrime);
resultPrime = new HashSet<>();
resultPrime.add(new UnifyPair(a, extAPrime, PairOperator.EQUALSDOT));
resultPrime.add(new UnifyPair(aPrime, thetaPrime, PairOperator.SMALLERDOT));
resultPrime = resultPrime.stream().map(x -> { x.setVariance(variance); return x;}).collect(Collectors.toCollection(HashSet::new));
result.add(resultPrime);
//writeLog("Result: " + resultPrime.toString());
return result;
}
/**
* Cartesian Product Case 3: (a <.? ? sup Theta')
*/
private Set<Set<UnifyPair>> unifyCase3(PlaceholderType a, SuperType subThetaPrime, byte variance, IFiniteClosure fc) {
Set<Set<UnifyPair>> result = new HashSet<>();
UnifyType aPrime = PlaceholderType.freshPlaceholder();
UnifyType supAPrime = new SuperType(aPrime);
UnifyType thetaPrime = subThetaPrime.getSuperedType();
Set<UnifyPair> resultPrime = new HashSet<>();
resultPrime.add(new UnifyPair(thetaPrime, a, PairOperator.SMALLERDOT));
result.add(resultPrime);
//writeLog(resultPrime.toString());
resultPrime = new HashSet<>();
resultPrime.add(new UnifyPair(a, supAPrime, PairOperator.EQUALSDOT));
resultPrime.add(new UnifyPair(thetaPrime, aPrime, PairOperator.SMALLERDOT));
resultPrime = resultPrime.stream().map(x -> { x.setVariance(variance); return x;}).collect(Collectors.toCollection(HashSet::new));
result.add(resultPrime);
//writeLog(resultPrime.toString());
return result;
}
/**
* Cartesian Product Case 5: (Theta <. a)
*/
private Set<Set<UnifyPair>> unifyCase5(UnifyType theta, PlaceholderType a, byte variance, IFiniteClosure fc) {
Set<Set<UnifyPair>> result = new HashSet<>();
boolean allGen = theta.getTypeParams().size() > 0;
for(UnifyType t : theta.getTypeParams())
if(!(t instanceof PlaceholderType) || !((PlaceholderType) t).isGenerated()) {
allGen = false;
break;
}
for(UnifyType thetaS : fc.greater(theta)) {
Set<UnifyPair> resultPrime = new HashSet<>();
UnifyType[] freshTphs = new UnifyType[thetaS.getTypeParams().size()];
for(int i = 0; !allGen && i < freshTphs.length; i++) {
freshTphs[i] = PlaceholderType.freshPlaceholder();
resultPrime.add(new UnifyPair(thetaS.getTypeParams().get(i), freshTphs[i], PairOperator.SMALLERDOTWC));
}
if(allGen)
resultPrime.add(new UnifyPair(a, thetaS, PairOperator.EQUALSDOT));
else
resultPrime.add(new UnifyPair(a, thetaS.setTypeParams(new TypeParams(freshTphs)), PairOperator.EQUALSDOT));
resultPrime = resultPrime.stream().map(x -> { x.setVariance(variance); return x;}).collect(Collectors.toCollection(HashSet::new));
result.add(resultPrime);
//writeLog(resultPrime.toString());
}
return result;
}
/**
* Cartesian Product Case 8: (Theta <.? a)
*/
private Set<Set<UnifyPair>> unifyCase8(UnifyType theta, PlaceholderType a, byte variance, IFiniteClosure fc) {
Set<Set<UnifyPair>> result = new HashSet<>();
//for(UnifyType thetaS : fc.grArg(theta)) {
Set<UnifyPair> resultPrime = new HashSet<>();
resultPrime.add(new UnifyPair(a, theta, PairOperator.EQUALSDOT));
result.add(resultPrime);
//writeLog(resultPrime.toString());
UnifyType freshTph = PlaceholderType.freshPlaceholder();
resultPrime = new HashSet<>();
resultPrime.add(new UnifyPair(a, new ExtendsType(freshTph), PairOperator.EQUALSDOT));
resultPrime.add(new UnifyPair(theta, freshTph, PairOperator.SMALLERDOT));
result.add(resultPrime);
//writeLog(resultPrime.toString());
resultPrime = new HashSet<>();
resultPrime.add(new UnifyPair(a, new SuperType(freshTph), PairOperator.EQUALSDOT));
resultPrime.add(new UnifyPair(freshTph, theta, PairOperator.SMALLERDOT));
resultPrime = resultPrime.stream().map(x -> { x.setVariance(variance); return x;}).collect(Collectors.toCollection(HashSet::new));
result.add(resultPrime);
//writeLog(resultPrime.toString());
//}
return result;
}
/**
* Takes a set of candidates for each position and computes all possible permutations.
* @param candidates The length of the list determines the number of type params. Each set
* contains the candidates for the corresponding position.
*/
protected Set<TypeParams> permuteParams(ArrayList<Set<UnifyType>> candidates) {
Set<TypeParams> result = new HashSet<>();
permuteParams(candidates, 0, result, new UnifyType[candidates.size()]);
return result;
}
/**
* Takes a set of candidates for each position and computes all possible permutations.
* @param candidates The length of the list determines the number of type params. Each set
* contains the candidates for the corresponding position.
* @param idx Idx for the current permutatiton.
* @param result Set of all permutations found so far
* @param current The permutation of type params that is currently explored
*/
private void permuteParams(ArrayList<Set<UnifyType>> candidates, int idx, Set<TypeParams> result, UnifyType[] current) {
if(candidates.size() == idx) {
result.add(new TypeParams(Arrays.copyOf(current, current.length)));
return;
}
Set<UnifyType> localCandidates = candidates.get(idx);
for(UnifyType t : localCandidates) {
current[idx] = t;
permuteParams(candidates, idx+1, result, current);
}
}
void writeLog(String str) {
try {
logFile.write(str+"\n");
logFile.flush();
}
catch (IOException e) { }
}
}

@ -1,117 +0,0 @@
package de.dhbwstuttgart.typeinference.unify.model;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* A pair which contains two types and an operator, e.q. (Integer <. a).
* @author Florian Steurer
*/
public class UnifyPair {
/**
* The type on the left hand side of the pair.
*/
private final UnifyType lhs;
/**
* The type on the right hand side of the pair.
*/
private final UnifyType rhs;
/**
* The operator that determines the relation between the left and right hand side type.
*/
private PairOperator pairOp;
private byte variance = 0;
private boolean undefinedPair = false;
private final int hashCode;
/**
* Creates a new instance of the pair.
* @param lhs The type on the left hand side of the pair.
* @param rhs The type on the right hand side of the pair.
* @param op The operator that determines the relation between the left and right hand side type.
*/
public UnifyPair(UnifyType lhs, UnifyType rhs, PairOperator op) {
this.lhs = lhs;
this.rhs = rhs;
pairOp = op;
// Caching hashcode
hashCode = 17 + 31 * lhs.hashCode() + 31 * rhs.hashCode() + 31 * pairOp.hashCode();
}
/**
* Returns the type on the left hand side of the pair.
*/
public UnifyType getLhsType() {
return lhs;
}
/**
* Returns the type on the right hand side of the pair.
*/
public UnifyType getRhsType() {
return rhs;
}
/**
* Returns the operator that determines the relation between the left and right hand side type.
*/
public PairOperator getPairOp() {
return pairOp;
}
public byte getVariance() {
return variance;
}
public void setVariance(byte v) {
variance = v;
}
public boolean isUndefinedPair() {
return undefinedPair;
}
@Override
public boolean equals(Object obj) {
if(!(obj instanceof UnifyPair))
return false;
if(obj.hashCode() != this.hashCode())
return false;
UnifyPair other = (UnifyPair) obj;
return other.getPairOp() == pairOp
&& other.getLhsType().equals(lhs)
&& other.getRhsType().equals(rhs);
}
@Override
public int hashCode() {
return hashCode;
}
@Override
public String toString() {
return "(" + lhs + " " + pairOp + " " + rhs + ")";
}
/*
public List<? extends PlaceholderType> getInvolvedPlaceholderTypes() {
ArrayList<PlaceholderType> ret = new ArrayList<>();
ret.addAll(lhs.getInvolvedPlaceholderTypes());
ret.addAll(rhs.getInvolvedPlaceholderTypes());
return ret;
}
*/
}

@ -17,6 +17,7 @@ import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import de.dhbwstuttgart.bytecode.Exception.BytecodeGeneratorError;
import de.dhbwstuttgart.bytecode.constraint.ExtendsConstraint;
import de.dhbwstuttgart.bytecode.constraint.TPHConstraint;
import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation;
@ -29,6 +30,7 @@ import de.dhbwstuttgart.bytecode.utilities.MethodAndTPH;
import de.dhbwstuttgart.bytecode.utilities.NormalConstructor;
import de.dhbwstuttgart.bytecode.utilities.NormalMethod;
import de.dhbwstuttgart.bytecode.utilities.Simplify;
import de.dhbwstuttgart.bytecode.utilities.SimplifyResult;
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal;
import de.dhbwstuttgart.syntaxtree.*;
import de.dhbwstuttgart.syntaxtree.statement.Literal;
@ -44,11 +46,11 @@ import de.dhbwstuttgart.typeinference.result.ResultPair;
import de.dhbwstuttgart.typeinference.result.ResultSet;
public class BytecodeGen implements ASTVisitor {
ClassWriter cw =new ClassWriter(ClassWriter.COMPUTE_FRAMES|ClassWriter.COMPUTE_MAXS);
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
String type;
public static RefTypeOrTPHOrWildcardOrGeneric THISTYPE = null;
String className;
private boolean isInterface;
@ -56,186 +58,222 @@ public class BytecodeGen implements ASTVisitor {
private ResultSet resultSet;
private SourceFile sf;
private String path;
private Optional<Constructor> fieldInitializations;
private int indexOfFirstParam = 0;
private String superClass;
private ArrayList<TypePlaceholder> tphsClass;
// stores parameter, local vars and the next index on the local variable table, which use for aload_i, astore_i,...
private ArrayList<String> tphsClass;
// stores parameter, local vars and the next index on the local variable table,
// which use for aload_i, astore_i,...
HashMap<String, Integer> paramsAndLocals = new HashMap<>();
// stores generics and their bounds of class
HashMap<String, String> genericsAndBounds = new HashMap<>();
private int constructorPos = 0;
private final TPHExtractor tphExtractor = new TPHExtractor();
private final ArrayList<GenericInsertPair> commonPairs = new ArrayList<>();
HashMap<String,RefTypeOrTPHOrWildcardOrGeneric> methodParamsAndTypes = new HashMap<>();
HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> methodParamsAndTypes = new HashMap<>();
byte[] bytecode;
HashMap<String,byte[]> classFiles;
ArrayList<String> methodNameAndParamsT = new ArrayList<>();
public BytecodeGen(HashMap<String,byte[]> classFiles, List<ResultSet> listOfResultSets,SourceFile sf ,String path) {
HashMap<String, byte[]> classFiles;
private final ArrayList<String> methodNameAndParamsT = new ArrayList<>();
private final ArrayList<String> fieldNameAndParamsT = new ArrayList<>();
private HashMap<String, SimplifyResult> simplifyResults = new HashMap<>();
private List<HashMap<String, SimplifyResult>> simplifyResultsList = new ArrayList<>();
private final ArrayList<String> fieldNameSignature = new ArrayList<>();
public List<HashMap<String, SimplifyResult>> getSimplifyResultsList() {
return simplifyResultsList;
}
public void setSimplifyResultsList(List<HashMap<String, SimplifyResult>> simplifyResultsList) {
this.simplifyResultsList = simplifyResultsList;
}
public BytecodeGen(HashMap<String, byte[]> classFiles, List<ResultSet> listOfResultSets, SourceFile sf,
String path) {
this.classFiles = classFiles;
this.listOfResultSets = listOfResultSets;
this.sf = sf;
this.path = path;
}
@Override
public void visit(SourceFile sourceFile) {
for(ClassOrInterface cl : sourceFile.getClasses()) {
for (ClassOrInterface cl : sourceFile.getClasses()) {
System.out.println("in Class: " + cl.getClassName().toString());
BytecodeGen classGen = new BytecodeGen(classFiles, listOfResultSets, sf, path);
cl.accept(classGen);
simplifyResultsList.add(classGen.getSimplifyResults());
classGen.writeClass(cl.getClassName().toString());
}
}
/**
* Associates the bytecode of the class that was build with the classWriter {@link #cw}
* with the class name in the map {@link #classFiles}
* Associates the bytecode of the class that was build with the classWriter
* {@link #cw} with the class name in the map {@link #classFiles}
*
* @param name name of the class with which the the bytecode is to be associated
*/
private void writeClass(String name) {
bytecode = cw.toByteArray();
classFiles.put(name, bytecode);
}
public HashMap<String,byte[]> getClassFiles() {
public HashMap<String, byte[]> getClassFiles() {
return classFiles;
}
@Override
public void visit(ClassOrInterface classOrInterface) {
className = classOrInterface.getClassName().toString();
cw.visitSource(className +".jav", null);
isInterface = (classOrInterface.getModifiers()&512)==512;
int acc = isInterface?classOrInterface.getModifiers()+Opcodes.ACC_ABSTRACT:classOrInterface.getModifiers()+Opcodes.ACC_SUPER;
className = classOrInterface.getClassName().toString();
cw.visitSource(className + ".jav", null);
isInterface = (classOrInterface.getModifiers() & 512) == 512;
int acc = isInterface ? classOrInterface.getModifiers() + Opcodes.ACC_ABSTRACT
: classOrInterface.getModifiers() + Opcodes.ACC_SUPER;
fieldInitializations = classOrInterface.getfieldInitializations();
// resultSet = listOfResultSets.get(0);
boolean isConsWithNoParamsVisited = false;
boolean isVisited = false;
for(ResultSet rs : listOfResultSets) {
for (ResultSet rs : listOfResultSets) {
superClass = classOrInterface.getSuperClass().acceptTV(new TypeToDescriptor());
resultSet = rs;
tphExtractor.setResultSet(resultSet);
// Nur einmal ausführen!!
if(!isVisited) {
if (!isVisited) {
classOrInterface.accept(tphExtractor);
getCommonTPHS(tphExtractor);
tphsClass = new ArrayList<>();
for(TypePlaceholder t : tphExtractor.allTPHS.keySet()) {
if(!tphExtractor.allTPHS.get(t))
for (String t : tphExtractor.allTPHS.keySet()) {
if (!tphExtractor.allTPHS.get(t))
tphsClass.add(t);
}
String sig = null;
/* if class has generics then creates signature
* Signature looks like:
* <E:Ljava/...>Superclass
/*
* if class has generics then creates signature Signature looks like:
* <E:Ljava/...>Superclass
*/
if(classOrInterface.getGenerics().iterator().hasNext() || !commonPairs.isEmpty() ||
classOrInterface.getSuperClass().acceptTV(new TypeToSignature()).contains("<")
if (classOrInterface.getGenerics().iterator().hasNext() || !commonPairs.isEmpty()
|| classOrInterface.getSuperClass().acceptTV(new TypeToSignature()).contains("<")
|| !tphsClass.isEmpty()) {
HashMap<TPHConstraint, HashSet<String>> constraints = Simplify.simplifyConstraintsClass(tphExtractor,tphsClass);
HashMap<TPHConstraint, HashSet<String>> constraints = Simplify
.simplifyConstraintsClass(tphExtractor, tphsClass);
ArrayList<TPHConstraint> consClass = new ArrayList<>();
for(TPHConstraint cons : constraints.keySet()) {
TypePlaceholder right = null;
for(TypePlaceholder tph : tphsClass) {
if(cons.getLeft().equals(tph.getName())) {
for (TPHConstraint cons : constraints.keySet()) {
String right = null;
boolean isToAdd = false;
for (String tph : tphsClass) {
if (cons.getLeft().equals(tph)) {
consClass.add(cons);
right = getTPH(cons.getRight());
try {
right = getTPH(cons.getRight());
isToAdd = true;
} catch (NoSuchElementException e) {
continue;
}
}
}
if(right != null) {
if (isToAdd) {
tphsClass.add(right);
removeFromMethod(right.getName());
removeFromMethod(right);
right = null;
isToAdd = false;
}
// if(right != null) {
// tphsClass.add(right);
// removeFromMethod(right);
// right = null;
// }
}
Signature signature = new Signature(classOrInterface, genericsAndBounds,commonPairs,tphsClass, consClass);
SimplifyResult sRes = new SimplifyResult(consClass, tphsClass, new HashMap<>());
simplifyResults.put(className, sRes);
Signature signature = new Signature(classOrInterface, genericsAndBounds, commonPairs, tphsClass,
consClass);
sig = signature.toString();
System.out.println("Signature: => " + sig);
}
cw.visit(Opcodes.V1_8, acc, classOrInterface.getClassName().toString()
, sig, classOrInterface.getSuperClass().acceptTV(new TypeToDescriptor()), null);
cw.visit(Opcodes.V1_8, acc, classOrInterface.getClassName().toString(), sig,
classOrInterface.getSuperClass().acceptTV(new TypeToDescriptor()), null);
isVisited = true;
}
for(Field f : classOrInterface.getFieldDecl()) {
for (Field f : classOrInterface.getFieldDecl()) {
f.accept(this);
}
for(Constructor c : classOrInterface.getConstructors()) {
for (Constructor c : classOrInterface.getConstructors()) {
// if(!isConsWithNoParamsVisited) {
c.accept(this);
c.accept(this);
// }
// if(!c.getParameterList().iterator().hasNext())
// isConsWithNoParamsVisited = true;
}
for(Method m : classOrInterface.getMethods()) {
for (Method m : classOrInterface.getMethods()) {
m.accept(this);
}
}
}
private void removeFromMethod(String name) {
for(MethodAndTPH m : tphExtractor.ListOfMethodsAndTph) {
for (MethodAndTPH m : tphExtractor.ListOfMethodsAndTph) {
ArrayList<String> toRemove = new ArrayList<>();
for(String tph : m.getTphs()) {
if(tph.equals(name)) {
for (String tph : m.getTphs()) {
if (tph.equals(name)) {
toRemove.add(tph);
}
}
if(!toRemove.isEmpty()) {
if (!toRemove.isEmpty()) {
m.getTphs().removeAll(toRemove);
return;
}
}
}
private TypePlaceholder getTPH(String name) {
for(TypePlaceholder tph: tphExtractor.allTPHS.keySet()) {
if(tph.getName().equals(name))
private String getTPH(String name) {
for (String tph : tphExtractor.allTPHS.keySet()) {
if (tph.equals(name))
return tph;
}
throw new NoSuchElementException("TPH "+name +" does not exist");
throw new NoSuchElementException("TPH " + name + " does not exist");
}
private void getCommonTPHS(TPHExtractor tphExtractor) {
// Gemeinsame TPHs
ArrayList<TypePlaceholder> cTPHs = new ArrayList<>();
ArrayList<String> cTPHs = new ArrayList<>();
// Alle TPHs der Felder speichern
for(TypePlaceholder tph : tphExtractor.allTPHS.keySet()) {
if(!tphExtractor.allTPHS.get(tph))
for (String tph : tphExtractor.allTPHS.keySet()) {
if (!tphExtractor.allTPHS.get(tph))
cTPHs.add(tph);
}
}
@ -243,156 +281,179 @@ public class BytecodeGen implements ASTVisitor {
@Override
public void visit(Constructor field) {
System.out.println("ResultSet: ");
resultSet.results.forEach(a->{
resultSet.results.forEach(a -> {
System.out.println(a.getLeft().toString() + " = " + a.getRight().toString());
});
System.out.println("---------------");
// stores generics and their bounds of method
HashMap<String, String> genericsAndBoundsMethod = new HashMap<>();
field.getParameterList().accept(this);
String methParamTypes = field.name+"%%";
String methParamTypes = field.name + "%%";
Iterator<FormalParameter> itr = field.getParameterList().iterator();
while(itr.hasNext()) {
while (itr.hasNext()) {
FormalParameter fp = itr.next();
methParamTypes += resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+";";
methParamTypes += resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor()) + ";";
// methParamTypes += resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToSignature())+";";
}
if(methodNameAndParamsT.contains(methParamTypes)) {
System.out.println("ignore - Method: "+field.name +" , paramsType: "+methParamTypes);
if (methodNameAndParamsT.contains(methParamTypes)) {
System.out.println("ignore - Method: " + field.name + " , paramsType: " + methParamTypes);
return;
}
methodNameAndParamsT.add(methParamTypes);
System.out.println("Method: "+field.name +" , paramsType: "+methParamTypes);
System.out.println("Method: " + field.name + " , paramsType: " + methParamTypes);
String desc = null;
boolean hasGen = false;
for(String paramName : methodParamsAndTypes.keySet()) {
for (String paramName : methodParamsAndTypes.keySet()) {
String typeOfParam = methodParamsAndTypes.get(paramName).acceptTV(new TypeToSignature());
System.out.println(typeOfParam);
if(genericsAndBounds.containsKey(typeOfParam) ||typeOfParam.contains("$")
|| typeOfParam.contains("<")) {
if (genericsAndBounds.containsKey(typeOfParam) || typeOfParam.contains("$") || typeOfParam.contains("<")) {
hasGen = true;
break;
}
}
String sig = null;
if(hasGen) {
HashMap<TPHConstraint, HashSet<String>> constraints = Simplify.simplifyConstraints(field.name, tphExtractor,tphsClass);
Signature signature = new Signature(field, genericsAndBounds,methodParamsAndTypes,resultSet,constraints);
if (hasGen) {
HashMap<TPHConstraint, HashSet<String>> constraints = Simplify.simplifyConstraints(field.name, tphExtractor,
tphsClass);
Signature signature = new Signature(field, genericsAndBounds, methodParamsAndTypes, resultSet, constraints);
sig = signature.toString();
}
if(field.getParameterList().iterator().hasNext())
if (field.getParameterList().iterator().hasNext())
System.out.println(field.getParameterList().iterator().next().getType().acceptTV(new TypeToDescriptor()));
NormalConstructor constructor = new NormalConstructor(field,genericsAndBounds,hasGen);
NormalConstructor constructor = new NormalConstructor(field, genericsAndBounds, hasGen);
desc = constructor.accept(new DescriptorToString(resultSet));
System.out.println("Constructor: " + field.getName() + " Sig: "+ sig + " Desc: " + desc);
System.out.println("Constructor: " + field.getName() + " Sig: " + sig + " Desc: " + desc);
MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", desc, sig, null);
mv.visitCode();
mv.visitCode();
Block block = fieldInitializations.get().block;
constructorPos += 1;
BytecodeGenMethod gen = new BytecodeGenMethod(className,superClass,resultSet,field, mv,paramsAndLocals,cw,
genericsAndBoundsMethod,genericsAndBounds,isInterface,classFiles, sf,path, block, constructorPos);
if(!field.getParameterList().iterator().hasNext() && !(field.block.statements.get(field.block.statements.size()-1) instanceof ReturnVoid)) {
BytecodeGenMethod gen = new BytecodeGenMethod(className, superClass, resultSet, field, mv, paramsAndLocals, cw,
genericsAndBoundsMethod, genericsAndBounds, isInterface, classFiles, sf, path, block, constructorPos);
if (!field.getParameterList().iterator().hasNext()
&& !(field.block.statements.get(field.block.statements.size() - 1) instanceof ReturnVoid)) {
mv.visitInsn(Opcodes.RETURN);
}
mv.visitMaxs(0, 0);
mv.visitEnd();
}
@Override
public void visit(Method method) {
// TODO: check if the method is static => if static then the first param will be stored in pos 0
// TODO: check if the method is static => if static then the first param will be
// stored in pos 0
// else it will be stored in pos 1 and this will be stored in pos 0
String retType = resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor());
// String retType = resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToSignature());
String methParamTypes = retType+method.name+"%%";
String methParamTypes = retType + method.name + "%%";
method.getParameterList().accept(this);
Iterator<FormalParameter> itr = method.getParameterList().iterator();
while(itr.hasNext()) {
while (itr.hasNext()) {
FormalParameter fp = itr.next();
methParamTypes += resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+";";
methParamTypes += resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor()) + ";";
// methParamTypes += resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToSignature())+";";
}
if(methodNameAndParamsT.contains(methParamTypes)) {
if (methodNameAndParamsT.contains(methParamTypes)) {
return;
}
methodNameAndParamsT.add(methParamTypes);
System.out.println("Method: "+method.name +" , paramsType: "+methParamTypes);
System.out.println("Method: " + method.name + " , paramsType: " + methParamTypes);
// stores generics and their bounds of method
HashMap<String, String> genericsAndBoundsMethod = new HashMap<>();
String methDesc = null;
// Method getModifiers() ?
int acc = isInterface?Opcodes.ACC_ABSTRACT:method.modifier;
int acc = isInterface ? Opcodes.ACC_ABSTRACT : method.modifier;
System.out.println(acc);
/*Prüfe, ob die Rückgabe-Type der Methode eine Type-Variable ist*/
boolean hasGenInParameterList = genericsAndBounds.containsKey(retType) || retType.subSequence(0, 4).equals("TPH ") ||
resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToSignature()).contains("<");
/*Wenn die Rückgabe-Type eine Typ-variable ist, erzeuge direkt die Signature, wenn nicht,
* prüfe, ob einer der Parameter Typ-Variable als Typ hat*/
if(!hasGenInParameterList) {
for(String paramName : methodParamsAndTypes.keySet()) {
/* Prüfe, ob die Rückgabe-Type der Methode eine Type-Variable ist */
boolean hasGenInParameterList = genericsAndBounds.containsKey(retType) || retType.contains("TPH ")
|| resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToSignature())
.contains("<");
/*
* Wenn die Rückgabe-Type eine Typ-variable ist, erzeuge direkt die Signature,
* wenn nicht, prüfe, ob einer der Parameter Typ-Variable als Typ hat
*/
if (!hasGenInParameterList) {
for (String paramName : methodParamsAndTypes.keySet()) {
String typeOfParam = methodParamsAndTypes.get(paramName).acceptTV(new TypeToDescriptor());
String sigOfParam = methodParamsAndTypes.get(paramName).acceptTV(new TypeToSignature());
if(genericsAndBounds.containsKey(typeOfParam)||typeOfParam.substring(0, 4).equals("TPH ")||sigOfParam.contains("<")) {
if (genericsAndBounds.containsKey(typeOfParam) || typeOfParam.contains("TPH ")
|| sigOfParam.contains("<")) {
hasGenInParameterList = true;
break;
}
}
}
//TODO: Test if the return-type or any of the parameter is a parameterized type. (VP)
//then create the descriptor with the new syntax.
// TODO: Test if the return-type or any of the parameter is a parameterized
// type. (VP)
// then create the descriptor with the new syntax.
String sig = null;
/* method.getGenerics: <....> RT method(..)
* */
/*
* method.getGenerics: <....> RT method(..)
*/
boolean hasGen = method.getGenerics().iterator().hasNext() || hasGenInParameterList;
/* if method has generics or return type is TPH, create signature */
// zwite operand muss weggelassen werden
if(hasGen||resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToString()).equals("TPH")) {
if (hasGen || resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToString())
.equals("TPH")) {
System.out.println("ALL CONST: " + tphExtractor.allCons.size());
tphExtractor.allCons.forEach(c->System.out.println(c.toString()));
tphExtractor.allCons.forEach(c -> System.out.println(c.toString()));
System.out.println("----------------");
HashMap<TPHConstraint, HashSet<String>> constraints = Simplify.simplifyConstraints(method.name, tphExtractor, tphsClass);
HashMap<TPHConstraint, HashSet<String>> constraints = Simplify.simplifyConstraints(method.name,
tphExtractor, tphsClass);
// ArrayList<GenericInsertPair> pairs = simplifyPairs(method.name,tphExtractor.allPairs,tphExtractor.allCons);
Signature signature = new Signature(method, genericsAndBoundsMethod, genericsAndBounds,methodParamsAndTypes,resultSet,constraints);
Signature signature = new Signature(method, genericsAndBoundsMethod, genericsAndBounds,
methodParamsAndTypes, resultSet, constraints);
sig = signature.toString();
}
System.out.println(method.getName()+" ==> "+sig);
NormalMethod meth = new NormalMethod(method,genericsAndBounds,genericsAndBoundsMethod,hasGen);
methDesc = meth.accept(new DescriptorToString(resultSet));
// System.out.println(methDesc);
MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC+acc, method.getName(), methDesc, sig, null);
if (simplifyResults.containsKey(className)) {
simplifyResults.get(className).getMethodsConstraints().put(methParamTypes, constraints);
} else {
SimplifyResult sRes = new SimplifyResult(new ArrayList<>(), new ArrayList<>(), new HashMap<>());
sRes.getMethodsConstraints().put(methParamTypes, constraints);
simplifyResults.put(className, sRes);
}
}
System.out.println(method.getName() + " ==> " + sig);
NormalMethod meth = new NormalMethod(method, genericsAndBounds, genericsAndBoundsMethod, hasGen);
methDesc = meth.accept(new DescriptorToString(resultSet));
// System.out.println(methDesc);
MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC + acc, method.getName(), methDesc, sig, null);
mv.visitCode();
BytecodeGenMethod gen = new BytecodeGenMethod(className, superClass, resultSet, method, mv, paramsAndLocals, cw,
genericsAndBoundsMethod, genericsAndBounds, isInterface, classFiles, sf, path);
mv.visitCode();
BytecodeGenMethod gen = new BytecodeGenMethod(className,superClass,resultSet,method, mv,paramsAndLocals,cw,
genericsAndBoundsMethod,genericsAndBounds,isInterface,classFiles, sf,path);
mv.visitMaxs(0, 0);
mv.visitEnd();
}
public HashMap<String, SimplifyResult> getSimplifyResults() {
return simplifyResults;
}
@Override
public void visit(ParameterList formalParameters) {
paramsAndLocals = new HashMap<>();
methodParamsAndTypes = new HashMap<>();
Iterator<FormalParameter> itr = formalParameters.iterator();
int i = 1;
while(itr.hasNext()) {
while (itr.hasNext()) {
FormalParameter fp = itr.next();
paramsAndLocals.put(fp.getName(), i);
methodParamsAndTypes.put(fp.getName(), resultSet.resolveType(fp.getType()).resolvedType);
@ -400,39 +461,39 @@ public class BytecodeGen implements ASTVisitor {
i++;
}
}
@Override
public void visit(FormalParameter formalParameter) {
formalParameter.getType().accept(this);
}
@Override
public void visit(RefType refType) {
type = "L"+refType.toString()+";";
type = "L" + refType.toString() + ";";
}
@Override
public void visit(SuperWildcardType superWildcardType) {
// TODO Auto-generated method stub
}
@Override
public void visit(TypePlaceholder typePlaceholder) {
// TODO Auto-generated method stub
}
@Override
public void visit(ExtendsWildcardType extendsWildcardType) {
// TODO Auto-generated method stub
}
@Override
public void visit(GenericRefType genericRefType) {
// TODO Auto-generated method stub
}
// ??
@ -440,41 +501,51 @@ public class BytecodeGen implements ASTVisitor {
public void visit(FieldVar fieldVar) {
System.out.println("In FieldVar ---");
// cw.newField(fieldVar.receiver.toString(), fieldVar.fieldVarName.toString(), fieldVar.getType().toString());
FieldVisitor fv = cw.visitField(Opcodes.ACC_PRIVATE, fieldVar.fieldVarName, "L"+fieldVar.getType()+";", null, null);
FieldVisitor fv = cw.visitField(Opcodes.ACC_PRIVATE, fieldVar.fieldVarName, "L" + fieldVar.getType() + ";",
null, null);
fv.visitEnd();
}
@Override
public void visit(Field field) {
System.out.println("In Field ---");
String des = "L";
if(resultSet.resolveType(field.getType()).resolvedType instanceof TypePlaceholder) {
if (resultSet.resolveType(field.getType()).resolvedType instanceof TypePlaceholder) {
des += Type.getInternalName(Object.class);
} else {
des += resultSet.resolveType(field.getType()).resolvedType.acceptTV(new TypeToDescriptor());
}
des +=";";
des += ";";
System.out.println(des);
String sig = resultSet.resolveType(field.getType()).resolvedType.acceptTV(new TypeToSignature());
System.out.println(sig);
if(sig.charAt(sig.length()-1) != (";").charAt(0)) {
sig +=";";
if (sig.charAt(sig.length() - 1) != (";").charAt(0)) {
sig += ";";
}
cw.visitField(field.modifier, field.getName(),
des, sig,
null);
String nameAndDesc = field.getName() + "%%" + des;
String nameAndSig = field.getName() + "%%" + sig;
if (fieldNameAndParamsT.contains(nameAndDesc)) {
if (fieldNameSignature.contains(nameAndSig)) {
return;
}
throw new BytecodeGeneratorError("Bytecode generation aborted due to duplicate field name&signature");
}
fieldNameAndParamsT.add(nameAndDesc);
fieldNameSignature.add(nameAndSig);
cw.visitField(field.modifier, field.getName(), des, sig, null);
}
@Override
public void visit(LambdaExpression lambdaExpression) {
// TODO Auto-generated method stub
}
@Override
public void visit(Assign assign) {
// TODO Auto-generated method stub
}
@Override
@ -485,151 +556,151 @@ public class BytecodeGen implements ASTVisitor {
@Override
public void visit(Block block) {
// TODO Auto-generated method stub
}
@Override
public void visit(CastExpr castExpr) {
// TODO Auto-generated method stub
}
@Override
public void visit(EmptyStmt emptyStmt) {
// TODO Auto-generated method stub
}
@Override
public void visit(ForStmt forStmt) {
// TODO Auto-generated method stub
}
@Override
public void visit(IfStmt ifStmt) {
// TODO Auto-generated method stub
}
@Override
public void visit(InstanceOf instanceOf) {
// TODO Auto-generated method stub
}
@Override
public void visit(LocalVar localVar) {
// TODO Auto-generated method stub
}
@Override
public void visit(LocalVarDecl localVarDecl) {
// TODO Auto-generated method stub
}
@Override
public void visit(MethodCall methodCall) {
// TODO Auto-generated method stub
}
@Override
public void visit(NewClass methodCall) {
// TODO Auto-generated method stub
}
@Override
public void visit(NewArray newArray) {
// TODO Auto-generated method stub
}
@Override
public void visit(Return aReturn) {
// TODO Auto-generated method stub
}
@Override
public void visit(ReturnVoid aReturn) {
// TODO Auto-generated method stub
}
@Override
public void visit(StaticClassName staticClassName) {
// TODO Auto-generated method stub
}
@Override
public void visit(Super aSuper) {
// TODO Auto-generated method stub
}
@Override
public void visit(This aThis) {
// TODO Auto-generated method stub
}
@Override
public void visit(WhileStmt whileStmt) {
// TODO Auto-generated method stub
}
@Override
public void visit(DoStmt whileStmt) {
// TODO Auto-generated method stub
}
// ???
@Override
public void visit(Literal literal) {
// TODO Auto-generated method stub
}
@Override
public void visit(ArgumentList argumentList) {
// TODO Auto-generated method stub
}
@Override
public void visit(GenericTypeVar genericTypeVar) {
// TODO Auto-generated method stub
}
@Override
public void visit(GenericDeclarationList genericTypeVars) {
// TODO Auto-generated method stub
}
@Override
public void visit(AssignToField assignLeftSide) {
// TODO Auto-generated method stub
}
@Override
public void visit(AssignToLocal assignLeftSide) {
// TODO Auto-generated method stub
}
@Override
public void visit(SuperCall superCall) {
}
@Override
@ -642,6 +713,5 @@ public class BytecodeGen implements ASTVisitor {
public void visit(UnaryExpr unaryExpr) {
throw new NotImplementedException();
}
}

@ -33,12 +33,14 @@ import org.objectweb.asm.Type;
import org.objectweb.asm.signature.SignatureVisitor;
import org.objectweb.asm.signature.SignatureWriter;
import de.dhbwstuttgart.bytecode.Exception.NotInCurrentPackageException;
import de.dhbwstuttgart.bytecode.descriptor.DescriptorToString;
import de.dhbwstuttgart.bytecode.descriptor.TypeToDescriptor;
import de.dhbwstuttgart.bytecode.signature.Signature;
import de.dhbwstuttgart.bytecode.signature.TypeToSignature;
import de.dhbwstuttgart.bytecode.utilities.KindOfLambda;
import de.dhbwstuttgart.bytecode.utilities.Lambda;
import de.dhbwstuttgart.bytecode.utilities.MethodCallHelper;
import de.dhbwstuttgart.bytecode.utilities.MethodFromMethodCall;
import de.dhbwstuttgart.bytecode.utilities.SamMethod;
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal;
@ -52,6 +54,7 @@ import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.result.ResultSet;
import javassist.NotFoundException;
public class BytecodeGenMethod implements StatementVisitor {
@ -140,7 +143,8 @@ public class BytecodeGenMethod implements StatementVisitor {
}
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) {
int indexOfFirstParamLam, boolean isInterface, HashMap<String, byte[]> classFiles, String path, int lamCounter, SourceFile sf,HashMap<String, String> genericsAndBoundsMethod,
HashMap<String, String> genericsAndBounds) {
this.resultSet = resultSet;
this.mv = mv;
@ -149,6 +153,9 @@ public class BytecodeGenMethod implements StatementVisitor {
this.path = path;
this.lamCounter = lamCounter;
this.sf = sf;
this.genericsAndBoundsMethod = genericsAndBoundsMethod;
this.genericsAndBounds = genericsAndBounds;
Iterator<FormalParameter> itr = lambdaExpression.params.iterator();
int i = indexOfFirstParamLam;
@ -644,7 +651,8 @@ public class BytecodeGenMethod implements StatementVisitor {
ArrayList<String> usedVars = kindOfLambda.getUsedVars();
new BytecodeGenMethod(lambdaExpression, usedVars,this.resultSet, mvLambdaBody, indexOfFirstParamLam, isInterface,
classFiles,this.path, lamCounter, sf);
classFiles,this.path, lamCounter, sf, genericsAndBoundsMethod,
genericsAndBounds);
mvLambdaBody.visitMaxs(0, 0);
mvLambdaBody.visitEnd();
@ -670,7 +678,7 @@ public class BytecodeGenMethod implements StatementVisitor {
}
methSig.visitReturnType().visitTypeVariable("R");
// ")"+lam.getReturn.getBounds
Signature sig = new Signature(lambdaExpression, numberOfParams);
Signature sig = new Signature(numberOfParams);
String name = "Fun" + numberOfParams + "$$";
classWriter.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC+Opcodes.ACC_INTERFACE + Opcodes.ACC_ABSTRACT, name, sig.toString(),
Type.getInternalName(Object.class), null);
@ -744,6 +752,13 @@ public class BytecodeGenMethod implements StatementVisitor {
statement = new IfStatement(ifStmt.expr, ifStmt.then_block, ifStmt.else_block);
isBinaryExp = statement.isExprBinary();
ifStmt.expr.accept(this);
if(!(ifStmt.expr instanceof BinaryExpr)) {
doUnboxing(getResolvedType(ifStmt.expr.getType()));
Label branchLabel = new Label();
Label endLabel = new Label();
mv.visitJumpInsn(Opcodes.IFEQ, branchLabel);
statement.genBCForRelOp(mv, branchLabel, endLabel, this);
}
statement = null;
}
@ -751,105 +766,112 @@ public class BytecodeGenMethod implements StatementVisitor {
public void visit(InstanceOf instanceOf) {
}
@Override
public void visit(MethodCall methodCall) {
boolean parentBinary = isParentBinary;
System.out.println("In MethodCall = " + methodCall.name);
String receiverName = getResolvedType(methodCall.receiver.getType());
System.out.println("Methods of " + receiverName + " ");
java.lang.reflect.Method methodRefl = null;
String clazz = receiverName.replace("/", ".");
String mDesc = "";
MethodCallHelper helper = new MethodCallHelper(methodCall, sf, resultSet, path);
boolean toCreate = false;
ClassLoader cLoader = ClassLoader.getSystemClassLoader();
// This will be used if the class is not standard class (not in API)
ClassLoader cLoader2;
java.lang.reflect.Method methodRefl = null;
String clazz = receiverName.replace("/", ".");
String methCallType = resultSet.resolveType(methodCall.getType()).resolvedType.acceptTV(new TypeToDescriptor());
String[] typesOfParams = getTypes(methodCall.arglist.getArguments());
try {
if(receiverName.contains("<")) {
if (receiverName.contains("<")) {
clazz = clazz.substring(0, receiverName.indexOf("<"));
}
java.lang.reflect.Method[] methods = cLoader.loadClass(clazz).getMethods();
System.out.println("Methods of " + receiverName + " ");
methodRefl = getMethod(methodCall.name,methodCall.arglist.getArguments().size(),methods);
} catch (Exception e) {
// try {
// cLoader2 = new URLClassLoader(new URL[] {new URL("file://"+path)});
// java.lang.reflect.Method[] methods = cLoader2.loadClass(clazz).getMethods();
// System.out.println("Methods of " + receiverName + " ");
// for(int i = 0; i<methods.length; i++) {
// System.out.println(methods[i]);
// }
// methodRefl = getMethod(methodCall.name,methodCall.arglist.getArguments().size(),methCallType, typesOfParams,methods);
// }catch (Exception e2) {
String superClass = "";
// TODO: Test SubMatrix.jav
while(true) {
for(ClassOrInterface cl : sf.getClasses()) {
if(receiverName.equals(cl.getClassName().toString())) {
superClass = cl.getSuperClass().getName().toString();
methodRefl = getMethod(methodCall.name, methodCall.arglist.getArguments().size(), methods);
} catch (Exception e) {
String superClass = "";
while(true) {
try {
superClass = helper.getSuperClass(receiverName);
try {
String superClazz = superClass.replace("/", ".");
if(superClass.contains("<")) {
superClazz = superClazz.substring(0, superClass.indexOf("<"));
}
java.lang.reflect.Method[] methods = cLoader.loadClass(superClazz).getMethods();
System.out.println("Methods of " + superClass + " ");
for(java.lang.reflect.Method m : methods) {
if(methodCall.name.equals(m.getName())) {
methodRefl = m;
break;
}
}
break;
} catch (Exception e3) {
receiverName = superClass;
continue;
}
} catch (NotInCurrentPackageException e2) {
break;
}
}
System.out.println(superClass);
if(superClass.equals(""))
break;
try {
String superClazz = superClass.replace("/", ".");
if(superClass.contains("<")) {
superClazz = superClazz.substring(0, superClass.indexOf("<"));
}
java.lang.reflect.Method[] methods = cLoader.loadClass(superClazz).getMethods();
System.out.println("Methods of " + superClass + " ");
for(java.lang.reflect.Method m : methods) {
if(methodCall.name.equals(m.getName())) {
methodRefl = m;
break;
}
}
break;
} catch (Exception e3) {
receiverName = superClass;
continue;
}
}
// }
}
}
if(methodRefl == null) {
try {
cLoader2 = new URLClassLoader(new URL[] {new URL("file://"+path)});
java.lang.reflect.Method[] methods = cLoader2.loadClass(clazz).getMethods();
System.out.println("Methods of " + receiverName + " ");
for(int i = 0; i<methods.length; i++) {
System.out.println(methods[i]);
if(methodRefl == null) {
toCreate = !receiverName.equals(className) && helper.isInCurrPkg(clazz);
if(toCreate) {
try {
mDesc = helper.getDesc(clazz);
} catch (NotInCurrentPackageException | NotFoundException e) {
e.printStackTrace();
}
} else if(!helper.isInCurrPkg(clazz)){
if(clazz.contains("$$")) {
mDesc = helper.generateBCForFunN();
}else {
try {
cLoader2 = new URLClassLoader(new URL[] {new URL("file://"+path)});
java.lang.reflect.Method[] methods = cLoader2.loadClass(clazz).getMethods();
System.out.println("Methods of " + receiverName + " ");
for(int i = 0; i<methods.length; i++) {
System.out.println(methods[i]);
}
methodRefl = getMethod(methodCall.name,methodCall.arglist.getArguments().size(),methCallType, typesOfParams,methods);
}
catch (Exception e2) {
e2.printStackTrace();
}
}
}
methodRefl = getMethod(methodCall.name,methodCall.arglist.getArguments().size(),methCallType, typesOfParams,methods);
}
catch (Exception e2) {
System.out.println("");
//do nothing
}
}
methodCall.receiver.accept(this);
System.out.println("Methodcall type : " + resultSet.resolveType(methodCall.getType()).resolvedType.acceptTV(new TypeToDescriptor()));
String mDesc = "";
List<Boolean> argListMethCall = new LinkedList<>();
String receiverRefl="";
if(methodRefl == null) {
if(methodRefl == null && receiverName.equals(className)) {
MethodFromMethodCall method = new MethodFromMethodCall(methodCall.arglist, methodCall.getType(),
receiverName, genericsAndBoundsMethod, genericsAndBounds);
mDesc = method.accept(new DescriptorToString(resultSet));
methodCall.arglist.accept(this);
} else {
} else if(methodRefl != null) {
System.out.println(methodCall.name + " -> Refl != null");
receiverRefl = methodRefl.getAnnotatedReceiverType().getType().toString();
for(Parameter p:methodRefl.getParameters()) {
System.out.println(p.getName() + " und is Primitive = " + p.getType().isPrimitive());
@ -863,9 +885,11 @@ public class BytecodeGenMethod implements StatementVisitor {
al.accept(argV);
statement = null;
}
} else {
methodCall.arglist.accept(this);
}
System.out.println("Methodcall Desc : " + mDesc);
System.out.println("Methodcall ("+ methodCall.name +") Desc : " + mDesc);
// methodCall.arglist.accept(this);
@ -900,6 +924,19 @@ public class BytecodeGenMethod implements StatementVisitor {
}
private String getDescForMethInCurrPkg(String name) {
// TODO Auto-generated method stub
return null;
}
private boolean isInCurrPkg(String superClass) {
for(ClassOrInterface cl : sf.KlassenVektor) {
if(superClass.equals(cl.getClassName().toString()))
return true;
}
return false;
}
private String[] getTypes(List<Expression> arguments) {
String[] types = new String[arguments.size()];
for(int i = 0; i<arguments.size(); ++i) {
@ -1197,6 +1234,7 @@ public class BytecodeGenMethod implements StatementVisitor {
break;
case "java/lang/Boolean":
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z", false);
break;
case "java/lang/Byte":
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B", false);
@ -1234,10 +1272,16 @@ public class BytecodeGenMethod implements StatementVisitor {
visitBooleanLiteral((Boolean) value);
break;
case "java/lang/Byte":
visitByteLiteral(((Double) value).byteValue(), false);
if(value instanceof Double)
visitByteLiteral(((Double) value).byteValue(), false);
if(value instanceof Integer)
visitByteLiteral(((Integer) value).byteValue(), false);
break;
case "java/lang/Short":
visitShortLiteral(((Double) value).shortValue(), false);
if(value instanceof Double)
visitShortLiteral(((Double) value).shortValue(), false);
if(value instanceof Integer)
visitShortLiteral(((Integer) value).shortValue(), false);
break;
case "java/lang/Integer":
// zweite Argument isLong
@ -1248,10 +1292,16 @@ public class BytecodeGenMethod implements StatementVisitor {
visitIntegerLiteral(((Integer) value).intValue(), false);
break;
case "java/lang/Long":
visitLongLiteral(((Integer) value).longValue(), true);
if(value instanceof Double)
visitLongLiteral(((Double) value).longValue(), true);
if(value instanceof Integer)
visitLongLiteral(((Integer) value).longValue(), true);
break;
case "java/lang/Float":
visitFloatLiteral(((Double) value).floatValue());
if(value instanceof Double)
visitFloatLiteral(((Double) value).floatValue());
if(value instanceof Integer)
visitFloatLiteral(((Integer) value).floatValue());
break;
case "java/lang/Double":
if(value instanceof Double)

@ -0,0 +1,19 @@
/**
*
*/
package de.dhbwstuttgart.bytecode.Exception;
/**
* @author fayez
*
*/
public class BytecodeGeneratorError extends RuntimeException {
/**
* @param message
*/
public BytecodeGeneratorError(String message) {
super(message);
}
}

@ -0,0 +1,25 @@
/**
*
*/
package de.dhbwstuttgart.bytecode.Exception;
/**
* @author fayez
*
*/
public class NotFoundException extends Exception {
/**
*
*/
private static final long serialVersionUID = 1L;
/**
* @param message
*/
public NotFoundException(String message) {
super(message);
}
}

@ -0,0 +1,26 @@
/**
*
*/
package de.dhbwstuttgart.bytecode.Exception;
/**
* @author fayez
*
*/
public class NotInCurrentPackageException extends Exception {
/**
*
*/
private static final long serialVersionUID = 1L;
/**
* @param message
*/
public NotInCurrentPackageException(String message) {
super(message);
}
}

@ -5,7 +5,11 @@ package de.dhbwstuttgart.bytecode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import de.dhbwstuttgart.bytecode.constraint.ExtendsConstraint;
import de.dhbwstuttgart.bytecode.constraint.TPHConstraint;
@ -13,13 +17,18 @@ import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation;
import de.dhbwstuttgart.bytecode.utilities.MethodAndTPH;
import de.dhbwstuttgart.syntaxtree.AbstractASTWalker;
import de.dhbwstuttgart.syntaxtree.Constructor;
import de.dhbwstuttgart.syntaxtree.Field;
import de.dhbwstuttgart.syntaxtree.FormalParameter;
import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.syntaxtree.ParameterList;
import de.dhbwstuttgart.syntaxtree.statement.LocalVar;
import de.dhbwstuttgart.syntaxtree.statement.LocalVarDecl;
import de.dhbwstuttgart.syntaxtree.type.GenericRefType;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.result.GenericInsertPair;
import de.dhbwstuttgart.typeinference.result.ResultPair;
import de.dhbwstuttgart.typeinference.result.ResultSet;
/**
@ -29,14 +38,14 @@ import de.dhbwstuttgart.typeinference.result.ResultSet;
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<>();
final HashMap<String, Boolean> allTPHS = new HashMap<>();
MethodAndTPH methodAndTph;
Boolean inMethod = false;
boolean inLocalOrParam = false;
public final ArrayList<MethodAndTPH> ListOfMethodsAndTph = new ArrayList<>();
final ArrayList<GenericInsertPair> allPairs = new ArrayList<>();
final ArrayList<ResultPair<TypePlaceholder, TypePlaceholder>> allPairs = new ArrayList<>();
public final ArrayList<TPHConstraint> allCons = new ArrayList<>();
private ResultSet resultSet;
@ -58,19 +67,80 @@ public class TPHExtractor extends AbstractASTWalker {
methodAndTph.getLocalTphs().add(resolvedTPH.getName());
}
allTPHS.put(resolvedTPH, inMethod);
resultSet.resolveType(tph).additionalGenerics.forEach(ag -> {
if (ag.contains(resolvedTPH) && ag.TA1.equals(resolvedTPH) && !contains(allPairs, ag)) {
allTPHS.put(resolvedTPH.getName(), inMethod);
// final List<TPHConstraint> cons = new ArrayList<>();
// resultSet.resolveType(tph).additionalGenerics.forEach(ag -> {
// TPHConstraint con = new ExtendsConstraint(ag.TA1.getName(), ag.TA2.getName(), Relation.EXTENDS);
// cons.add(con);
// });
//
// Map<TPHConstraint, Boolean> visitMap = new HashMap<>();
// for(TPHConstraint cc : cons) {
// visitMap.put(cc, false);
// }
//
// String left = resolvedTPH.getName();
// for (TPHConstraint cc : visitMap.keySet()) {
//
// if(visitMap.get(cc))
// continue;
//
// if (cc.getLeft().equals(left)) {
// allCons.add(cc);
// List<TPHConstraint> toVisit = getToVisitCons(cons,cc.getRight(), visitMap);
// }
// }
//resultSet.resolveType(tph).getAdditionalGenerics().forEach(ag -> {
resultSet.genIns.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);
}
TPHConstraint con = new ExtendsConstraint(ag.getLeft().getName(), ag.getRight().getName(), Relation.EXTENDS);
if(!containsConstraint(allCons,con))
allCons.add(con);
// }
});
} else if (resultSet.resolveType(tph).resolvedType instanceof RefType) {
RefType rt = (RefType) resultSet.resolveType(tph).resolvedType;
rt.accept(this);
}
}
private static boolean containsConstraint(ArrayList<TPHConstraint> allCons, TPHConstraint c) {
for(TPHConstraint con:allCons) {
if(c.getLeft().equals(con.getLeft()) && c.getRight().equals(c.getRight())) {
return true;
}
}
return false;
}
private List<TPHConstraint> getToVisitCons(List<TPHConstraint> cons, String right, Map<TPHConstraint, Boolean> visitMap) {
List<TPHConstraint> res = new ArrayList<>();
for(TPHConstraint cc : cons) {
if(cc.getLeft().equals(right)) {
res.add(cc);
if(visitMap.get(cc))
visitMap.replace(cc, false);
}
}
return res;
}
@Override
public void visit(GenericRefType genericRefType) {
String name = genericRefType.getParsedName();
if (inMethod) {
methodAndTph.getLocalTphs().add(name);
if (inLocalOrParam)
methodAndTph.getLocalTphs().add(name);
}
allTPHS.put(name, inMethod);
}
private boolean contains(ArrayList<GenericInsertPair> pairs, GenericInsertPair genPair) {
for (int i = 0; i < pairs.size(); ++i) {
GenericInsertPair p = pairs.get(i);

@ -1,5 +1,6 @@
package de.dhbwstuttgart.bytecode.descriptor;
import java.util.HashMap;
import java.util.Iterator;
import org.objectweb.asm.Type;
@ -44,17 +45,28 @@ public class DescriptorToString implements DescriptorVisitor{
if(method.hasGen()) {
String fpDesc = fp.getType().acceptTV(new TypeToDescriptor());
if(method.getGenericsAndBoundsMethod().containsKey(fpDesc)) {
desc += "L"+method.getGenericsAndBoundsMethod().get(fpDesc)+ ";";
String bound = getBound(fpDesc, method.getGenericsAndBoundsMethod());
desc += "L"+bound+ ";";
}else if(method.getGenericsAndBounds().containsKey(fpDesc)){
desc += "L"+method.getGenericsAndBounds().get(fpDesc)+ ";";
String bound = getBound(fpDesc, method.getGenericsAndBounds());
desc += "L"+bound+ ";";
}else {
// desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";";
String resType = resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor());
if(resType.subSequence(0, 4).equals("TPH ")) {
if(resType.contains("TPH ")/*resType.subSequence(0, 4).equals("TPH ")*/) {
// Bound ist immer Object
desc += "L"+Type.getInternalName(Object.class)+ ";";
} else {
desc += "L"+resType+ ";";
// TODO::
if(method.getGenericsAndBounds().containsKey(resType)) {
String bound = getBound(resType, method.getGenericsAndBounds());
desc += "L"+bound+ ";";
}else if(method.getGenericsAndBoundsMethod().containsKey(resType)) {
String bound = getBound(resType, method.getGenericsAndBoundsMethod());
desc += "L"+bound+ ";";
} else {
desc += "L"+resType+ ";";
}
}
}
}
@ -78,11 +90,21 @@ public class DescriptorToString implements DescriptorVisitor{
desc += ")L"+method.getGenericsAndBounds().get(ret)+ ";";
}else {
String resType = resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor());
if(resType.subSequence(0, 4).equals("TPH ")) {
if(resType.contains("TPH ")/*resType.subSequence(0, 4).equals("TPH ")*/) {
// desc += ")" + "L"+method.getGenericsAndBoundsMethod().get(resType.substring(4)+"$")+ ";";
desc += ")" + "L"+Type.getInternalName(Object.class)+ ";";
} else {
desc += ")" + "L"+resType+ ";";
// TODO::
if(method.getGenericsAndBounds().containsKey(resType)) {
String bound = getBound(resType, method.getGenericsAndBounds());
desc += ")L"+bound+ ";";
}else if(method.getGenericsAndBoundsMethod().containsKey(resType)) {
String bound = getBound(resType, method.getGenericsAndBoundsMethod());
desc += ")L"+bound+ ";";
} else {
desc += ")L"+resType+ ";";
}
// desc += ")" + "L"+resType+ ";";
}
}
}else {
@ -93,6 +115,15 @@ public class DescriptorToString implements DescriptorVisitor{
return desc;
}
private String getBound(String fpDesc, HashMap<String, String> genericsAndBounds) {
String start = genericsAndBounds.get(fpDesc);
while(genericsAndBounds.containsKey(start)) {
start = genericsAndBounds.get(start);
}
return start;
}
@Override
public String visit(NormalConstructor constructor) {
String desc = "(";
@ -131,7 +162,7 @@ public class DescriptorToString implements DescriptorVisitor{
while(itr.hasNext()) {
FormalParameter fp = itr.next();
String d = resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor());
if(d.substring(0, 4).equals("TPH ") ||d.contains("<")) {
if(d.contains("TPH ") ||d.contains("<")) {
desc += "L"+Type.getInternalName(Object.class)+ ";";
}else {
desc = desc + "L"+ d + ";";
@ -140,7 +171,7 @@ public class DescriptorToString implements DescriptorVisitor{
String retType = resultSet.resolveType(lambdaExpression.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor());
if(retType.substring(0, 4).equals("TPH ")|| retType.contains("<")){
if(retType.contains("TPH ")|| retType.contains("<")){
desc += ")L"+Type.getInternalName(Object.class)+ ";";
}else {
desc = desc + ")"+"L"+retType+";";
@ -156,7 +187,7 @@ public class DescriptorToString implements DescriptorVisitor{
RefTypeOrTPHOrWildcardOrGeneric rt = itr.next();
String d = resultSet.resolveType(rt).resolvedType.acceptTV(new TypeToDescriptor());
if(d.substring(0, 4).equals("TPH ") ||d.contains("<")) {
if(d.contains("TPH ") ||d.contains("<")) {
desc += "L"+Type.getInternalName(Object.class)+ ";";
}else {
desc += "L"+ d + ";";
@ -165,7 +196,7 @@ public class DescriptorToString implements DescriptorVisitor{
}
String retType = resultSet.resolveType(samMethod.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor());
if(retType.substring(0, 4).equals("TPH ")|| retType.contains("<")){
if(retType.contains("TPH ")|| retType.contains("<")){
desc += ")L"+Type.getInternalName(Object.class)+ ";";
}else {
desc = desc + ")"+"L"+retType+";";
@ -179,7 +210,7 @@ public class DescriptorToString implements DescriptorVisitor{
for(Expression e : methodFromMethodCall.getArgList().getArguments()) {
String d = resultSet.resolveType(e.getType()).resolvedType.acceptTV(new TypeToDescriptor());
if(d.substring(0, 4).equals("TPH ") ||d.contains("<") || methodFromMethodCall.getReceiverName().contains("$$")) {
if(d.contains("TPH ") ||d.contains("<") || methodFromMethodCall.getReceiverName().contains("$$")) {
desc += "L"+Type.getInternalName(Object.class)+ ";";
}else {
if(methodFromMethodCall.getGenericsAndBoundsMethod().containsKey(d)) {
@ -196,7 +227,7 @@ public class DescriptorToString implements DescriptorVisitor{
System.out.println("DescriptorToString retType = " + retType);
if(retType.equals("void")) {
desc += ")V";
}else if(retType.substring(0, 4).equals("TPH ")|| retType.contains("<") || methodFromMethodCall.getReceiverName().contains("$$")){
}else if(retType.contains("TPH ")|| retType.contains("<") || methodFromMethodCall.getReceiverName().contains("$$")){
desc += ")L"+Type.getInternalName(Object.class)+ ";";
}else {
if(methodFromMethodCall.getGenericsAndBoundsMethod().containsKey(retType)) {

@ -41,11 +41,11 @@ public class Signature {
private ResultSet resultSet;
private ArrayList<GenericInsertPair> commonPairs;
private HashMap<TPHConstraint,HashSet<String>> methodConstraints;
private ArrayList<TypePlaceholder> tphsClass;
private ArrayList<String> tphsClass;
private ArrayList<TPHConstraint> consClass;
public Signature(ClassOrInterface classOrInterface, HashMap<String, String> genericsAndBounds,
ArrayList<GenericInsertPair> commonPairs, ArrayList<TypePlaceholder> tphsClass, ArrayList<TPHConstraint> consClass) {
ArrayList<GenericInsertPair> commonPairs, ArrayList<String> tphsClass, ArrayList<TPHConstraint> consClass) {
this.classOrInterface = classOrInterface;
this.genericsAndBounds = genericsAndBounds;
this.commonPairs = commonPairs;
@ -80,12 +80,12 @@ public class Signature {
createSignatureForConsOrMethod(this.method,false);
}
public Signature(LambdaExpression lambdaExpression,int numberOfParams) {
public Signature(int numberOfParams) {
sw = new SignatureWriter();
createSignatureForFunN(lambdaExpression, numberOfParams);
createSignatureForFunN(numberOfParams);
}
private void createSignatureForFunN(LambdaExpression lambdaExpression, int numberOfParams) {
private void createSignatureForFunN(int numberOfParams) {
// sw.visitClassBound().visitEnd();
for(int i = 0;i<numberOfParams;i++) {
@ -235,8 +235,9 @@ public class Signature {
RefTypeOrTPHOrWildcardOrGeneric resolved = resType.resolvedType;
if(resolved instanceof TypePlaceholder) {
resType.additionalGenerics.forEach(ag ->{
TPHConstraint constr = new ExtendsConstraint(ag.TA1.getName(), ag.TA2.getName(), Relation.EXTENDS);
//resType.getAdditionalGenerics().forEach(ag ->{
resultSet.genIns.forEach(ag ->{
TPHConstraint constr = new ExtendsConstraint(ag.getLeft().getName(), ag.getRight().getName(), Relation.EXTENDS);
if(!contains(res,constr)) {
res.add(constr);
}
@ -246,8 +247,9 @@ public class Signature {
WildcardType resWC = (WildcardType) resolved;
ResolvedType resType2 = resultSet.resolveType(resWC.getInnerType());
if(resType2.resolvedType instanceof TypePlaceholder) {
resType2.additionalGenerics.forEach(ag ->{
TPHConstraint constr = new ExtendsConstraint(ag.TA1.getName(), ag.TA2.getName(), Relation.EXTENDS);
//resType2.getAdditionalGenerics().forEach(ag ->{
resultSet.genIns.forEach(ag ->{
TPHConstraint constr = new ExtendsConstraint(ag.getLeft().getName(), ag.getRight().getName(), Relation.EXTENDS);
if(!contains(res,constr)) {
res.add(constr);
}
@ -290,7 +292,8 @@ public class Signature {
break;
case "GRT":
GenericRefType g = (GenericRefType) t;
sv.visitTypeVariable(g.acceptTV(new TypeToSignature()).substring(1));
// sv.visitTypeVariable(g.acceptTV(new TypeToSignature()).substring(1));
sv.visitTypeVariable(g.acceptTV(new TypeToSignature()));
break;
case "TPH":
RefTypeOrTPHOrWildcardOrGeneric r = resultSet.resolveType(t).resolvedType;
@ -301,16 +304,27 @@ public class Signature {
// das braucht man nicht es reicht: sv.visitTypeVariable(r.acceptTV(new TypeToSignature())
//
String sig2 = r.acceptTV(new TypeToSignature());
String eqTPH = getEqualTPH(methodConstraints, sig2.substring(1, sig2.length()-1))+"$";
if(!(r instanceof TypePlaceholder)) {
if(r instanceof GenericRefType) {
sv.visitTypeVariable(sig2);
}else if(!(r instanceof TypePlaceholder)) {
if(sig2.contains("$$")) {
System.out.println(" Signature FUN$$: "+r);
sv.visitInterface().visitClassType(sig2.substring(1, sig2.length()));
} else {
sv.visitClassType(sig2.substring(1, sig2.length()));
// Kann zwischen GenericRefType und RefType nicht unterscheiden
// Deswegen wird immer geprüft, ob der Name in Generic Maps liegt
String n = sig2.substring(1, sig2.length()-1);
// if(genericsAndBoundsMethod.containsKey(n) || genericsAndBounds.containsKey(n)) {
// sv.visitTypeVariable(n);
// } else {
sv.visitClassType(n);
sv.visitEnd();
// }
// sv.visitClassType(n);
}
} else {
String eqTPH = getEqualTPH(methodConstraints, sig2.substring(1, sig2.length()-1))+"$";
System.out.println(r.getClass()+" Signature TPH: "+r.acceptTV(new TypeToSignature()));
sv.visitTypeVariable(eqTPH);
}
@ -456,10 +470,15 @@ public class Signature {
String boundDesc = b.acceptTV(new TypeToDescriptor());
// System.out.println("GetBounds: " + boundDesc);
// Ensure that <...> extends java.lang.Object OR ...
sw.visitClassBound().visitClassType(boundDesc);
if(b instanceof GenericRefType) {
sw.visitClassBound().visitTypeVariable(boundDesc);
} else {
sw.visitClassBound().visitClassType(boundDesc);
sw.visitClassBound().visitEnd();
}
genAndBounds.put(g.getName(), boundDesc);
}
sw.visitClassBound().visitEnd();
// sw.visitClassBound().visitEnd();
}
public String toString() {

@ -2,14 +2,17 @@ package de.dhbwstuttgart.bytecode.utilities;
import java.util.ArrayList;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.result.GenericInsertPair;
import de.dhbwstuttgart.typeinference.result.ResultPair;
public class MethodAndTPH {
private String name;
private final ArrayList<String> tphs = new ArrayList<>();
private final ArrayList<GenericInsertPair> pairs = new ArrayList<>();
//private final ArrayList<GenericInsertPair> pairs = new ArrayList<>();
private final ArrayList<ResultPair<TypePlaceholder, TypePlaceholder>> pairs = new ArrayList<>();
// tphs of local variables and parameters
private final ArrayList<String> localTphs = new ArrayList<>();
@ -21,7 +24,10 @@ public class MethodAndTPH {
return tphs;
}
public ArrayList<GenericInsertPair> getPairs(){
// public ArrayList<GenericInsertPair> getPairs(){
// return pairs;
// }
public ArrayList<ResultPair<TypePlaceholder, TypePlaceholder>> getPairs(){
return pairs;
}

@ -0,0 +1,255 @@
/**
*
*/
package de.dhbwstuttgart.bytecode.utilities;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.signature.SignatureVisitor;
import org.objectweb.asm.signature.SignatureWriter;
import de.dhbwstuttgart.bytecode.Exception.NotInCurrentPackageException;
import de.dhbwstuttgart.bytecode.descriptor.DescriptorToString;
import de.dhbwstuttgart.bytecode.descriptor.TypeToDescriptor;
import de.dhbwstuttgart.bytecode.signature.Signature;
import de.dhbwstuttgart.bytecode.signature.TypeToSignature;
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
import de.dhbwstuttgart.syntaxtree.FormalParameter;
import de.dhbwstuttgart.syntaxtree.GenericDeclarationList;
import de.dhbwstuttgart.syntaxtree.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.syntaxtree.SourceFile;
import de.dhbwstuttgart.syntaxtree.statement.Expression;
import de.dhbwstuttgart.syntaxtree.statement.LambdaExpression;
import de.dhbwstuttgart.syntaxtree.statement.MethodCall;
import de.dhbwstuttgart.syntaxtree.type.GenericRefType;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.result.ResultSet;
import javassist.NotFoundException;
/**
* @author fayez
*
*/
public class MethodCallHelper {
private MethodCall methCall;
private SourceFile sourceFile;
private ResultSet resultSet;
private String path;
/**
* @param methCall
* @param sourceFile
* @param resultSet
* @param path TODO
*/
public MethodCallHelper(MethodCall methCall, SourceFile sourceFile, ResultSet resultSet, String path) {
this.methCall = methCall;
this.sourceFile = sourceFile;
this.resultSet = resultSet;
this.path = path;
}
public String getResolvedType(RefTypeOrTPHOrWildcardOrGeneric type) {
return resultSet.resolveType(type).resolvedType.acceptTV(new TypeToDescriptor());
}
public boolean isInCurrPkg(String className) {
for (ClassOrInterface cl : sourceFile.KlassenVektor) {
if (className.equals(cl.getClassName().toString()))
return true;
}
return false;
}
public String getSuperClass(String className) throws NotInCurrentPackageException {
for (ClassOrInterface cl : sourceFile.getClasses()) {
if (className.equals(cl.getClassName().toString())) {
return cl.getSuperClass().getName().toString();
}
}
throw new NotInCurrentPackageException("Class " + className + " is not in the current package.");
}
public ClassOrInterface getClassFromCurrPkg(String className) throws NotInCurrentPackageException {
for (ClassOrInterface cl : sourceFile.KlassenVektor) {
if (className.equals(cl.getClassName().toString()))
return cl;
}
throw new NotInCurrentPackageException("Class of " + className + " is not in the current package.");
}
public String getDesc(String className) throws NotInCurrentPackageException, NotFoundException {
String name = methCall.name;
ClassOrInterface clazz = getClassFromCurrPkg(className);
Map<String, String> genAndBoundsClass = getGenericsAndBounds(clazz.getGenerics());
modifyGenAndBounds(genAndBoundsClass);
for (Method m : clazz.getMethods()) {
if (name.equals(m.getName())) {
Map<String, String> genAndBoundsMethod = getGenericsAndBoundsMethod(m.getGenerics());
modifyGenAndBounds(genAndBoundsMethod);
boolean hasGen = hasGen(m, genAndBoundsClass);
NormalMethod nm = new NormalMethod(m, (HashMap<String, String>) genAndBoundsClass,
(HashMap<String, String>) genAndBoundsMethod, hasGen);
return nm.accept(new DescriptorToString(resultSet));
}
}
throw new NotFoundException("Method " + name + " is not found");
}
private boolean hasGen(Method m, Map<String, String> genericsAndBounds) {
String retType = resultSet.resolveType(m.getReturnType()).resolvedType.acceptTV(new TypeToSignature());
/*Prüfe, ob die Rückgabe-Type der Methode eine Type-Variable ist*/
boolean hasGenInParameterList = genericsAndBounds.containsKey(retType) || retType.contains("TPH ") || retType.contains("<");
Map<String,RefTypeOrTPHOrWildcardOrGeneric> methodParamsAndTypes = new HashMap<>();
Iterator<FormalParameter> itr = m.getParameterList().iterator();
while(itr.hasNext()) {
FormalParameter fp = itr.next();
methodParamsAndTypes.put(fp.getName(), resultSet.resolveType(fp.getType()).resolvedType);
}
/*Wenn die Rückgabe-Type eine Typ-variable ist, erzeuge direkt die Signature, wenn nicht,
* prüfe, ob einer der Parameter Typ-Variable als Typ hat*/
if(!hasGenInParameterList) {
for(String paramName : methodParamsAndTypes.keySet()) {
String typeOfParam = methodParamsAndTypes.get(paramName).acceptTV(new TypeToDescriptor());
String sigOfParam = methodParamsAndTypes.get(paramName).acceptTV(new TypeToSignature());
if(genericsAndBounds.containsKey(typeOfParam)||typeOfParam.contains("TPH ")||sigOfParam.contains("<")) {
hasGenInParameterList = true;
break;
}
}
}
return m.getGenerics().iterator().hasNext() || hasGenInParameterList;
}
private Map<String, String> getGenericsAndBoundsMethod(Iterable<? extends GenericTypeVar> generics) {
Map<String, String> genAndBounds = new HashMap<>();
Iterator<? extends GenericTypeVar> itr = generics.iterator();
while (itr.hasNext()) {
GenericTypeVar gtv = itr.next();
getBoundsOfTypeVar(gtv, genAndBounds);
}
return genAndBounds;
}
private void modifyGenAndBounds(Map<String, String> genAndBoundsClass) {
List<String> visited = new ArrayList<>(genAndBoundsClass.size());
Map<String, String> toReplace = new HashMap<>();
for (String tv : genAndBoundsClass.keySet()) {
if (visited.contains(tv))
continue;
List<String> types = new LinkedList<>();
String bound = genAndBoundsClass.get(tv);
types.add(tv);
visited.add(tv);
boolean doReplace = false;
while (genAndBoundsClass.keySet().contains(bound)) {
doReplace = true;
types.add(bound);
visited.add(bound);
bound = genAndBoundsClass.get(bound);
}
if (doReplace) {
for (String tt : types) {
toReplace.put(tt, bound);
}
}
}
for (String key : toReplace.keySet()) {
genAndBoundsClass.replace(key, toReplace.get(key));
}
}
private Map<String, String> getGenericsAndBounds(GenericDeclarationList generics) {
Map<String, String> genAndBounds = new HashMap<>();
Iterator<GenericTypeVar> itr = generics.iterator();
while (itr.hasNext()) {
GenericTypeVar gtv = itr.next();
getBoundsOfTypeVar(gtv, genAndBounds);
}
return genAndBounds;
}
private void getBoundsOfTypeVar(GenericTypeVar g, Map<String, String> genAndBounds) {
Iterator<? extends RefTypeOrTPHOrWildcardOrGeneric> bItr = g.getBounds().iterator();
while (bItr.hasNext()) {
RefTypeOrTPHOrWildcardOrGeneric b = bItr.next();
String boundDesc = b.acceptTV(new TypeToDescriptor());
genAndBounds.put(g.getName(), boundDesc);
}
}
public String generateBCForFunN() {
ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
SignatureWriter methSig = new SignatureWriter();
int numberOfParams = 0;
SignatureVisitor paramVisitor = methSig.visitParameterType();
Iterator<Expression> itr1 = methCall.arglist.getArguments().iterator();
String methDesc = "(";
while(itr1.hasNext()) {
numberOfParams++;
// getBounds
paramVisitor.visitTypeVariable("T" + numberOfParams);
methDesc += "L" + Type.getInternalName(Object.class) + ";";
itr1.next();
}
methDesc += ")L" + Type.getInternalName(Object.class) + ";";
methSig.visitReturnType().visitTypeVariable("R");
// ")"+lam.getReturn.getBounds
Signature sig = new Signature(numberOfParams);
String name = "Fun" + numberOfParams + "$$";
classWriter.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC+Opcodes.ACC_INTERFACE + Opcodes.ACC_ABSTRACT, name, sig.toString(),
Type.getInternalName(Object.class), null);
MethodVisitor mvApply = classWriter.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_ABSTRACT, "apply", methDesc,
methSig.toString(), null);
mvApply.visitEnd();
writeClassFile(classWriter.toByteArray(), name);
return methDesc;
}
private void writeClassFile(byte[] bytecode, String name) {
FileOutputStream output;
try {
System.out.println("generating " + name + ".class file...");
output = new FileOutputStream(
new File(path + name + ".class"));
output.write(bytecode);
output.close();
System.out.println(name + ".class file generated");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}

@ -23,6 +23,7 @@ public class MethodFromMethodCall {
this.genericsAndBounds = genericsAndBounds;
}
public ArgumentList getArgList() {
return argList;
}

@ -19,7 +19,7 @@ import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
public class Simplify {
public static HashMap<TPHConstraint, HashSet<String>> simplifyConstraints(String name, TPHExtractor tphExtractor,
ArrayList<TypePlaceholder> tphsClass) {
ArrayList<String> tphsClass) {
// 1. check if there are any simple cycles like L<R and R<L:
// a) yes => set L=R and:
// * remove both constraints
@ -38,8 +38,10 @@ public class Simplify {
ArrayList<TPHConstraint> allCons = new ArrayList<>();
for(TPHConstraint c : tphExtractor.allCons) {
TPHConstraint nc = new TPHConstraint(c.getLeft(), c.getRight(), c.getRel());
allCons.add(nc);
if(!containsConstraint(allCons,c)) {
TPHConstraint nc = new TPHConstraint(c.getLeft(), c.getRight(), c.getRel());
allCons.add(nc);
}
}
ArrayList<TPHConstraint> consToRemove = new ArrayList<>();
@ -382,7 +384,7 @@ public class Simplify {
if (!containTPH(methodTphs, superTphRes)) {
HashSet<String> equals = getEqualsTphsFromEqualCons(eqCons, superTphRes);
if (classTPHSContainsTPH(tphsClass, superTphRes)) {
if (tphsClass.contains(superTphRes)/*classTPHSContainsTPH(tphsClass, superTphRes)*/) {
result.put(new ExtendsConstraint(subTphRes, superTphRes, Relation.EXTENDS), equals);
} else {
result.put(new ExtendsConstraint(subTphRes, Type.getInternalName(Object.class), Relation.EXTENDS),
@ -450,6 +452,15 @@ public class Simplify {
return result;
}
private static boolean containsConstraint(ArrayList<TPHConstraint> allCons, TPHConstraint c) {
for(TPHConstraint con:allCons) {
if(c.getLeft().equals(con.getLeft()) && c.getRight().equals(c.getRight())) {
return true;
}
}
return false;
}
private static void updateEqualCons(Map<String, List<String>> replRes, ArrayList<TPHConstraint> eqCons) {
List<String> oldNames = replRes.values().iterator().next();
String newName = replRes.keySet().iterator().next();
@ -463,7 +474,7 @@ public class Simplify {
}
public static HashMap<TPHConstraint, HashSet<String>> simplifyConstraintsClass(TPHExtractor tphExtractor,
ArrayList<TypePlaceholder> tphsClass) {
ArrayList<String> tphsClass) {
// all constraints that will be simplified
ArrayList<TPHConstraint> allCons = tphExtractor.allCons;
ArrayList<TPHConstraint> consToRemove = new ArrayList<>();
@ -627,7 +638,9 @@ public class Simplify {
if (isTPHInConstraint(result, sub))
continue;
if (!classTPHSContainsTPH(tphsClass, sub))
// if (!classTPHSContainsTPH(tphsClass, sub))
// continue;
if (!tphsClass.contains(sub))
continue;
if (numOfVisitedPairs >= size)
@ -656,7 +669,7 @@ public class Simplify {
// add X at the beginning of the list.
while (subAndSuper.containsValue(subTphRes)) {
for (String tph : subAndSuper.keySet()) {
if (classTPHSContainsTPH(tphsClass, tph) && subAndSuper.get(tph).equals(subTphRes)) {
if (/*classTPHSContainsTPH(tphsClass, tph)*/tphsClass.contains(tph) && subAndSuper.get(tph).equals(subTphRes)) {
subTphRes = tph;
break;
}

@ -0,0 +1,42 @@
/**
*
*/
package de.dhbwstuttgart.bytecode.utilities;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import de.dhbwstuttgart.bytecode.constraint.TPHConstraint;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
/**
* @author fayez
*
*/
public class SimplifyResult {
private final ArrayList<TPHConstraint> classConstraints;
private final ArrayList<String> tphsClass;
private final HashMap<String, HashMap<TPHConstraint, HashSet<String>>> methodsConstraints;
public SimplifyResult(ArrayList<TPHConstraint> classConstraints, ArrayList<String> tphsClass,
HashMap<String, HashMap<TPHConstraint, HashSet<String>>> methodsConstraints) {
super();
this.classConstraints = classConstraints;
this.tphsClass = tphsClass;
this.methodsConstraints = methodsConstraints;
}
public ArrayList<TPHConstraint> getClassConstraints() {
return classConstraints;
}
public HashMap<String, HashMap<TPHConstraint, HashSet<String>>> getMethodsConstraints() {
return methodsConstraints;
}
public ArrayList<String> getTphsClass() {
return tphsClass;
}
}

@ -3,6 +3,8 @@ package de.dhbwstuttgart.core;
import de.dhbwstuttgart.bytecode.BytecodeGen;
import de.dhbwstuttgart.bytecode.Exception.BytecodeGeneratorError;
import de.dhbwstuttgart.bytecode.utilities.SimplifyResult;
import de.dhbwstuttgart.environment.CompilationEnvironment;
import de.dhbwstuttgart.parser.JavaTXParser;
import de.dhbwstuttgart.parser.NullToken;
@ -50,6 +52,7 @@ import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.antlr.v4.parse.ANTLRParser.throwsSpec_return;
import org.apache.commons.io.output.NullOutputStream;
//import org.apache.commons.io.output.NullOutputStream;
public class JavaTXCompiler {
@ -58,7 +61,14 @@ public class JavaTXCompiler {
Boolean resultmodel = false;
public final Map<File, SourceFile> sourceFiles = new HashMap<>();
Boolean log = true; //gibt an ob ein Log-File nach System.getProperty("user.dir")+"src/test/java/logFiles" geschrieben werden soll?
/**
* Äußerste Liste der Source-Files.
* Danach Liste der Klassen in Source File.
* Danach Map Klassenname
*/
private List<List<HashMap<String, SimplifyResult>>> simplifyResultsSF = new ArrayList<>();
public JavaTXCompiler(File sourceFile) throws IOException, ClassNotFoundException {
this(Arrays.asList(sourceFile));
}
@ -555,8 +565,8 @@ public class JavaTXCompiler {
}
/* UnifyResultModel End */
else {
Set<Set<UnifyPair>> result = unify.unify(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, logFile, log, new UnifyResultModel(cons, finiteClosure));
//Set<Set<UnifyPair>> result = unify.unifyOderConstraints(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, logFile, log, new UnifyResultModel(cons, finiteClosure));
//Set<Set<UnifyPair>> result = unify.unify(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, logFile, log, new UnifyResultModel(cons, finiteClosure));
Set<Set<UnifyPair>> result = unify.unifyOderConstraints(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, logFile, log, new UnifyResultModel(cons, finiteClosure));
System.out.println("RESULT: " + result);
logFile.write("RES: " + result.toString()+"\n");
logFile.flush();
@ -642,7 +652,7 @@ public class JavaTXCompiler {
return ret;
}
// um pfad erweitern
public void generateBytecode(String path) throws ClassNotFoundException, IOException {
public void generateBytecode(String path) throws ClassNotFoundException, IOException, BytecodeGeneratorError {
for(File f : sourceFiles.keySet()) {
HashMap<String,byte[]> classFiles = new HashMap<>();
SourceFile sf = sourceFiles.get(f);
@ -650,6 +660,7 @@ public class JavaTXCompiler {
BytecodeGen bytecodeGen = new BytecodeGen(classFiles,typeinferenceResult,sf,path);
// BytecodeGen bytecodeGen = new BytecodeGen(classFiles,typeinferenceResult.get(0));
bytecodeGen.visit(sf);
this.simplifyResultsSF.add(bytecodeGen.getSimplifyResultsList());
this.writeClassFile(bytecodeGen.getClassFiles(), path);
}
}
@ -666,4 +677,8 @@ public class JavaTXCompiler {
System.out.println(name+".class file generated");
}
}
public List<List<HashMap<String, SimplifyResult>>> getSimplifyResults() {
return simplifyResultsSF;
}
}

@ -100,7 +100,7 @@ public class UnifyTypeFactory {
}
ret = new ReferenceType(t.getName().toString(),new TypeParams(params));
}else{
ret = new ReferenceType(t.getName().toString());
ret = new ReferenceType(t.getName().toString(), false);
}
return ret;
}
@ -136,7 +136,7 @@ public class UnifyTypeFactory {
}
public static UnifyType convert(GenericRefType t, Boolean innerType){
return new ReferenceType(t.getParsedName());
return new ReferenceType(t.getParsedName(), true);
}
public static UnifyType convert(WildcardType t, Boolean innerType){
@ -222,12 +222,15 @@ public class UnifyTypeFactory {
return new PairTPHequalRefTypeOrWildcardType((TypePlaceholder)tl, (RefType) tr);
}else if(tr instanceof WildcardType){
return new PairTPHequalRefTypeOrWildcardType((TypePlaceholder)tl, (WildcardType) tr);
}else if(tr instanceof GenericRefType){
return new PairTPHequalRefTypeOrWildcardType((TypePlaceholder)tl, (GenericRefType) tr);
}else throw new NotImplementedException();
}else throw new NotImplementedException();
}
public static RefTypeOrTPHOrWildcardOrGeneric convert(ReferenceType t, Map<String,TypePlaceholder> tphs) {
if(JavaClassName.Void.equals(t.getName()))return new Void(new NullToken());
if (t.isGenTypeVar()) return new GenericRefType(t.getName(),new NullToken());
RefType ret = new RefType(new JavaClassName(t.getName()),convert(t.getTypeParams(), tphs),new NullToken());
return ret;
}

@ -1,9 +1,6 @@
package de.dhbwstuttgart.typedeployment;
import org.antlr.v4.runtime.Token;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@ -32,7 +32,7 @@ public class TypeInsertFactory {
ResolvedType resolvedType = resultSet.resolveType(type);
TypeInsertPoint insertPoint = new TypeInsertPoint(offset,
new TypeToInsertString(resolvedType.resolvedType).insert);
return new TypeInsert(insertPoint, new HashSet<>(Arrays.asList(createGenericInsert(resolvedType.additionalGenerics, cl, m))));
return new TypeInsert(insertPoint, new HashSet<>());
}
private static TypeInsertPoint createGenericInsert(Set<GenericInsertPair> toInsert, ClassOrInterface cl, Method m){

@ -8,7 +8,7 @@ import java.util.List;
import java.util.stream.Collectors;
public class TypeInsertPoint {
public final Token point;
public Token point;
private String insertString;
public TypeInsertPoint(Token point, String toInsert){
@ -28,6 +28,14 @@ public class TypeInsertPoint {
return insertString;
}
public Token getToken() {
return this.point;
}
public void setToken(Token point) {
this.point = point;
}
/* PL 2018-06-19
* Zwei TypeInsertPoint's sind gleich, wenn ihre point's gleich sind
* eingefuegt damit man TypeReplaceMarker vergleichen kann

@ -23,4 +23,9 @@ public class GenericInsertPair {
if(TA2.equals(additionalTPH))return true;
return false;
}
@Override
public String toString() {
return "GenIns(" + TA1.toString() + " < " + TA2.toString() + ")";
}
}

@ -21,4 +21,9 @@ public class PairTPHequalRefTypeOrWildcardType extends ResultPair{
public void accept(ResultPairVisitor visitor) {
visitor.visit(this);
}
@Override
public String toString() {
return "(" + left.toString() + " = " + right.toString() + ")";
}
}

@ -20,4 +20,9 @@ public class PairTPHsmallerTPH extends ResultPair{
public void accept(ResultPairVisitor visitor) {
visitor.visit(this);
}
@Override
public String toString() {
return "(" + left.toString() + " < " + right.toString() + ")";
}
}

@ -8,10 +8,10 @@ import java.util.Set;
public class ResolvedType{
public final RefTypeOrTPHOrWildcardOrGeneric resolvedType;
public final Set<GenericInsertPair> additionalGenerics;
//public final Set<GenericInsertPair> additionalGenerics;
public ResolvedType(RefTypeOrTPHOrWildcardOrGeneric resolvedType, Set<GenericInsertPair> additionalGenerics){
this.resolvedType = resolvedType;
this.additionalGenerics = additionalGenerics;
//this.additionalGenerics = additionalGenerics;
}
}

@ -6,11 +6,16 @@ import de.dhbwstuttgart.syntaxtree.type.*;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;
public class ResultSet {
public final Set<ResultPair> results;
public Set<ResultPair<TypePlaceholder, TypePlaceholder>> genIns;
public ResultSet(Set<ResultPair> results){
this.results = results;
this.genIns = results.stream().filter(a -> a instanceof PairTPHsmallerTPH)
//.map(b -> new GenericInsertPair( (TypePlaceholder)(b.getLeft()), (TypePlaceholder)(b.getRight())))
.collect(Collectors.toCollection(HashSet::new));
}
public ResolvedType resolveType(RefTypeOrTPHOrWildcardOrGeneric type) {

@ -19,6 +19,10 @@ import java.util.function.BinaryOperator;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.commons.io.output.NullOutputStream;
import de.dhbwstuttgart.exceptions.TypeinferenceException;
import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory;
import de.dhbwstuttgart.typeinference.constraints.Constraint;
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
@ -44,6 +48,7 @@ import de.dhbwstuttgart.typeinference.unify.model.Pair;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import com.google.common.collect.Ordering;
@ -163,7 +168,9 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
thNo = totalnoOfThread;
writeLog("thNo2 " + thNo);
try {
this.logFile = new FileWriter(new File(System.getProperty("user.dir")+"/src/test/java/logFiles/"+"Thread_"+thNo));
this.logFile = //new OutputStreamWriter(new NullOutputStream());
new FileWriter(new File(System.getProperty("user.dir")+"/src/test/java/logFiles/"+"Thread_"+thNo));
//logFile.write("");
}
catch (IOException e) {
System.err.println("log-File nicht vorhanden");
@ -228,7 +235,9 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
catch (IOException ioE) {
System.err.println("no log-File");
}
if (isUndefinedPairSetSet(res)) { return new HashSet<>(); }
if (isUndefinedPairSetSet(res)) {
throw new TypeinferenceException("Unresolved constraints: " + res.toString(), new NullToken()); //return new HashSet<>();
}
else return res;
}
/*
@ -478,15 +487,16 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
//PL 2018-05-18 beide Bedingungen muessen gelten, da eqPrime Veränderungen in allem ausser subst
//eqPrimePrime Veraenderungen in subst repraesentieren.
//try {
if (isSolvedForm(eqPrime)) {
writeLog("eqPrime:" + eqPrime.toString()+"\n");
}
//if (isSolvedForm(eqPrime)) {
// writeLog("eqPrime:" + eqPrime.toString()+"\n");
//}
//}
//catch (IOException e) {
// System.err.println("log-File nicht vorhanden");
//}
eqPrimePrimeSet.add(eqPrime);
if (finalresult) {
if (finalresult && isSolvedForm(eqPrime)) {
writeLog("eqPrime:" + eqPrime.toString()+"\n");
urm.notify(eqPrimePrimeSet);
}
}
@ -542,7 +552,7 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
return result;
}
Set<Set<UnifyPair>> nextSet = remainingSets.remove(0);
writeLog("nextSet: " + nextSet.toString());
if (finalresult) writeLog("nextSet: " + nextSet.toString());
List<Set<UnifyPair>> nextSetasList =new ArrayList<>(nextSet);
try {
//List<Set<UnifyPair>>
@ -611,9 +621,9 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
System.out.print("");
if (nextSetasList.iterator().next().stream().filter(x -> x.getLhsType().getName().equals("D")).findFirst().isPresent() && nextSetasList.size()>1)
System.out.print("");
writeLog("nextSetasList: " + nextSetasList.toString());
if (finalresult) writeLog("nextSetasList: " + nextSetasList.toString());
Set<UnifyPair> nextSetElem = nextSetasList.get(0);
writeLog("BasePair1: " + nextSetElem + " " + nextSetElem.iterator().next().getBasePair());
if (finalresult) writeLog("BasePair1: " + nextSetElem + " " + nextSetElem.iterator().next().getBasePair());
/* sameEqSet-Bestimmung: Wenn a = ty \in nextSet dann enthaelt sameEqSet alle Paare a < ty1 oder ty2 < a aus fstElems */
Set<UnifyPair> sameEqSet = new HashSet<>();
@ -747,7 +757,7 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
//for(Set<UnifyPair> a : newSet) {
i++;
Set<Set<UnifyPair>> elems = new HashSet<Set<UnifyPair>>(fstElems);
writeLog("a1: " + rekTiefe + " "+ "variance: "+ variance + " " + a.toString()+ "\n");
if (finalresult) writeLog("a1: " + rekTiefe + " "+ "variance: "+ variance + " " + a.toString()+ "\n");
//elems.add(a); PL 2019-01-20 Muss weg, weil das in jeweiligen Thread erfolgen muss. Fuer den sequentiellen Fall
//im else-Zweig
//if (remainingSets.isEmpty()) {//muss immer gegeben sein, weil nur 1 Element der topLevelSets mehr als ein Elemet enthaelt
@ -1341,7 +1351,7 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
// .collect(Collectors.toCollection(ArrayList::new));
writeLog("res (undef): " + res.toString());
writeLog("abhSubst: " + abhSubst.toString());
writeLog("a2: " + rekTiefe + " " + a.toString());
if (finalresult) writeLog("a2: " + rekTiefe + " " + a.toString());
writeLog("Durchschnitt: " + durchschnitt.toString());
writeLog("nextSet: " + nextSet.toString());
writeLog("nextSetasList: " + nextSetasList.toString());

@ -11,28 +11,45 @@ import de.dhbwstuttgart.typeinference.unify.interfaces.UnifyTypeVisitor;
* @author Florian Steurer
*
*/
public final class ReferenceType extends UnifyType {
public class ReferenceType extends UnifyType {
/**
* The buffered hashCode
*/
private final int hashCode;
/**
* gibt an, ob der ReferenceType eine generische Typvariable ist
*/
private final boolean genericTypeVar;
public <T> UnifyType accept(UnifyTypeVisitor<T> visitor, T ht) {
return visitor.visit(this, ht);
}
public ReferenceType(String name, Boolean genericTypeVar) {
super(name, new TypeParams());
hashCode = 31 + 17 * typeName.hashCode() + 17 * typeParams.hashCode();
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();
genericTypeVar = false;
}
public boolean isGenTypeVar () {
return genericTypeVar;
}
@Override
Set<UnifyType> smArg(IFiniteClosure fc, Set<UnifyType> fBounded) {
return fc.smArg(this, fBounded);

@ -0,0 +1,37 @@
package bytecode;
import static org.junit.Assert.*;
import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import org.junit.BeforeClass;
import org.junit.Test;
import de.dhbwstuttgart.core.JavaTXCompiler;
public class ClassGenLamTest {
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")+"/src/test/resources/bytecode/javFiles/ClassGenLam.jav";
fileToTest = new File(path);
compiler = new JavaTXCompiler(fileToTest);
pathToClassFile = System.getProperty("user.dir")+"/src/test/resources/testBytecode/generatedBC/";
compiler.generateBytecode(pathToClassFile);
loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)});
classToTest = loader.loadClass("ClassGenLam");
instanceOfClass = classToTest.getDeclaredConstructor().newInstance();
}
}

@ -0,0 +1,38 @@
package bytecode;
import static org.junit.Assert.*;
import java.io.File;
import java.lang.reflect.Field;
import java.net.URL;
import java.net.URLClassLoader;
import org.junit.BeforeClass;
import org.junit.Test;
import de.dhbwstuttgart.core.JavaTXCompiler;
public class TypedIDTest {
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 test() throws Exception {
path = System.getProperty("user.dir")+"/src/test/resources/bytecode/javFiles/TypedID.jav";
fileToTest = new File(path);
compiler = new JavaTXCompiler(fileToTest);
compiler.generateBytecode(System.getProperty("user.dir")+"/src/test/resources/testBytecode/generatedBC/");
pathToClassFile = System.getProperty("user.dir")+"/src/test/resources/testBytecode/generatedBC/";
loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)});
classToTest = loader.loadClass("TypedID");
instanceOfClass = classToTest.getDeclaredConstructor().newInstance();
}
}

@ -0,0 +1,45 @@
package bytecode;
import static org.junit.Assert.*;
import java.io.File;
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 VectorSuperTest {
private static String path;
private static File fileToTest;
private static JavaTXCompiler compiler;
private static ClassLoader loader;
private static Class<?> classToTest;
private static String pathToClassFile;
private static Object instanceOfClass;
@BeforeClass
public static void setUpBeforeClass() throws Exception {
path = System.getProperty("user.dir")+"/src/test/resources/bytecode/javFiles/VectorSuper.jav";
fileToTest = new File(path);
compiler = new JavaTXCompiler(fileToTest);
pathToClassFile = System.getProperty("user.dir")+"/src/test/resources/testBytecode/generatedBC/";
compiler.generateBytecode(pathToClassFile);
loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)});
classToTest = loader.loadClass("VectorSuper");
instanceOfClass = classToTest.getDeclaredConstructor().newInstance();
}
@Test
public void test1() throws Exception {
Method m = classToTest.getDeclaredMethod("m", Vector.class);
//Object result = m.invoke(instanceOfClass, 1);
//assertEquals(1,result);
}
}

@ -1,3 +1,4 @@
package bytecode;
import static org.junit.Assert.assertEquals;

@ -0,0 +1,8 @@
import java.lang.Integer;
public class ClassGenLam {
lam = x-> x;
// public ClassGenLam() {
// lam = x->x;
// }
}

@ -1,22 +1,25 @@
import java.lang.Integer;
import java.lang.Long;
import java.lang.Short;
public class Faculty {
public fact;
Faculty() {
fact = (x) -> {
if (x == 1) {
return 1;
}
else {
return x * (fact.apply(x-1));
}
};
}
public getFact(x) {
return fact.apply(x);
}
public fact;
Faculty() {
fact = (x) -> {
if (x == 1) {
return 1;
}
else {
return x * (fact.apply(x-1));
}
};
}
public getFact(x) {
return fact.apply(x);
}
}
// m (x) {
//
//// var fact = (x) -> {
@ -45,4 +48,4 @@ public class Faculty {
// return x * m(x-1);
// }
// }
}

@ -1,6 +1,7 @@
public class Id<FTU extends FTT,FTT> {
public class Id {
id(FTU b){
id(b){
return b;
}
}
}

@ -1,6 +1,6 @@
import java.util.Vector;
import java.lang.Integer;
import java.lang.Byte;
//import java.lang.Byte;
import java.lang.Boolean;
public class MatrixOP extends Vector<Vector<Integer>> {
@ -18,7 +18,7 @@ public class MatrixOP extends Vector<Vector<Integer>> {
}
}
Fun2$$<java.util.Vector<? extends java.util.Vector<? extends java.lang.Byte>>, java.util.Vector<? extends java.util.Vector<? extends java.lang.Byte>>, MatrixOP> mul = (m1, m2) -> {
public Fun2$$<java.util.Vector<? extends java.util.Vector<? extends java.lang.Integer>>, java.util.Vector<? extends java.util.Vector<? extends java.lang.Integer>>, MatrixOP> mul = (m1, m2) -> {
var ret = new MatrixOP();
var i = 0;
while(i < m1.size()) {

@ -10,8 +10,6 @@ public class OL {
}
public class OLMain {
main(x) {

@ -0,0 +1,12 @@
public class TypedID/*<L extends K,K> */ {
lam = x-> x;
id(b){
return b;
}
m(){
return lam;
}
}

@ -0,0 +1,11 @@
import java.util.Vector;
import java.lang.Integer;
public class VectorSuper {
m(x){
Integer y = 1;
x.addElement(y);
//return x;
}
}