Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5dccbffebd | |||
| 76f2048797 | |||
| a1195b689d | |||
| 3cd61778d6 | |||
| 021d3e1b27 | |||
| c90f01d5db | |||
| 8b3b018ea9 | |||
| 210adaa493 |
@@ -0,0 +1,19 @@
|
|||||||
|
import java.util.stream.Stream;
|
||||||
|
import Pair;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public class Kombinatoren_After {
|
||||||
|
|
||||||
|
|
||||||
|
after (fst, snd) { //System.out.println("after2");
|
||||||
|
|
||||||
|
return () -> Stream.of(
|
||||||
|
toks -> {
|
||||||
|
return fst.apply().flatMap(x ->
|
||||||
|
x.apply(toks).flatMap(p1 ->
|
||||||
|
snd.apply().flatMap(y -> y.apply(p1.snd()).map(p2 ->
|
||||||
|
new Pair<>(new Pair<>(p1.fst(), p2.fst()), p2.snd()))))); } );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import java.util.stream.Stream;
|
||||||
|
import Pair;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public class Kombinatoren_After_Lazy {
|
||||||
|
|
||||||
|
|
||||||
|
afterP (fst, snd) {
|
||||||
|
return toks -> {
|
||||||
|
return fst.apply(toks).flatMap(p1 ->
|
||||||
|
snd.apply(p1.snd()).map(p2 ->
|
||||||
|
new Pair<>(new Pair<>(p1.fst(), p2.fst()), p2.snd())));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import java.util.stream.Stream;
|
||||||
|
import Pair;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public class Kombinatoren_Or {
|
||||||
|
|
||||||
|
|
||||||
|
orP (p1, p2) {
|
||||||
|
return ()-> Stream.concat(p1.apply(), p2.apply());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
after (fst, snd) { //System.out.println("after2");
|
||||||
|
|
||||||
|
return () -> Stream.of(
|
||||||
|
toks -> {
|
||||||
|
return fst.apply().flatMap(x ->
|
||||||
|
x.apply(toks).flatMap(p1 ->
|
||||||
|
snd.apply().flatMap(y -> y.apply(p1.snd()).map(p2 ->
|
||||||
|
new Pair<>(new Pair<>(p1.fst(), p2.fst()), p2.snd()))))); } );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
trans (p, f) {
|
||||||
|
return () -> p.apply().map(x -> (toks -> x.apply(toks).map(pr -> new Pair<>(f.apply(pr.fst()), pr.snd() ) ) ) );
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
import java.util.stream.Stream;
|
||||||
|
//import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import java.lang.System;
|
||||||
|
|
||||||
|
//import java.lang.String;
|
||||||
|
import java.lang.Boolean;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import Pair;
|
||||||
|
import Kombinatoren_failure;
|
||||||
|
|
||||||
|
public class Kombinatoren_Satisfy {
|
||||||
|
|
||||||
|
kb = new Kombinatoren_failure();
|
||||||
|
|
||||||
|
satisfy(cond) {
|
||||||
|
// return () -> Stream.of (newToks -> new Kombinatoren_failure().failure().apply().map(x -> x.apply(newToks)));
|
||||||
|
//}
|
||||||
|
return () -> Stream.of (toks -> {
|
||||||
|
if(toks.isEmpty()) {
|
||||||
|
return new ArrayList<>().stream();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var fst = toks.getFirst();
|
||||||
|
if (cond.apply(fst))
|
||||||
|
{
|
||||||
|
//var newToks = List.copyOf(toks.subList(1, toks.size()));
|
||||||
|
var newToks = new ArrayList<>(toks);
|
||||||
|
return newToks.removeFirst();
|
||||||
|
kb.getContent(
|
||||||
|
kb.succeed(fst).apply().map(x -> x.apply(newToks))
|
||||||
|
);
|
||||||
|
// ;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/* () -> Stream.of (toks -> {
|
||||||
|
//System.out.println(toks);
|
||||||
|
if(toks.isEmpty())
|
||||||
|
{
|
||||||
|
return new ArrayList<>().stream();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var fst = toks.getFirst();
|
||||||
|
if (cond.apply(fst))
|
||||||
|
{
|
||||||
|
var newToks = List.copyOf(toks.subList(1, toks.size()));
|
||||||
|
//System.out.println("satisfy ok " + fst.toString());
|
||||||
|
//return get(succeed(fst).apply().map(x -> x.apply(newToks)));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//System.out.println("satisfy failure " + fst.toString());
|
||||||
|
//return get(failure().apply()).apply(toks);
|
||||||
|
}
|
||||||
|
return new ArrayList<>().stream();
|
||||||
|
} } ) ;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import java.util.stream.Stream;
|
||||||
|
import Pair;
|
||||||
|
//import java.util.function.Function;
|
||||||
|
|
||||||
|
public class Kombinatoren_Trans {
|
||||||
|
|
||||||
|
|
||||||
|
trans (p, f) {
|
||||||
|
return () -> p.apply().map(x -> (toks -> x.apply(toks).map(pr -> new Pair<>(f.apply(pr.fst()), pr.snd() ) ) ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
import java.util.stream.Stream;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import java.lang.System;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import java.lang.String;
|
||||||
|
import java.lang.Boolean;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import Pair;
|
||||||
|
|
||||||
|
|
||||||
|
public class Kombinatoren_failure {
|
||||||
|
public getContent(s) {
|
||||||
|
return s.toList().getFirst();
|
||||||
|
}
|
||||||
|
|
||||||
|
public failure() {
|
||||||
|
return () -> Stream.of(
|
||||||
|
toks -> new ArrayList<>().stream());
|
||||||
|
}
|
||||||
|
public succeed( value) {
|
||||||
|
return () -> Stream.of(toks -> {
|
||||||
|
//System.out.println("succeed");
|
||||||
|
var al = new ArrayList<>();
|
||||||
|
al.add(new Pair<>(value, toks));
|
||||||
|
//al.forEach(x -> { System.out.println(x.toString());});
|
||||||
|
return al.stream();});
|
||||||
|
}
|
||||||
|
|
||||||
|
parser(p, inp) {
|
||||||
|
return p.map(y -> y.apply(
|
||||||
|
inp.chars().mapToObj(c -> (char) c)
|
||||||
|
.collect(Collectors.toList())))
|
||||||
|
.flatMap(x -> x)
|
||||||
|
.filter(x -> x.snd().isEmpty())
|
||||||
|
.findFirst()
|
||||||
|
.get()
|
||||||
|
.fst();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
|
||||||
|
satisfy(cond) {
|
||||||
|
return newToks -> failure().apply().map(x -> x.apply(newToks));
|
||||||
|
/*
|
||||||
|
return () -> Stream.of (toks -> {
|
||||||
|
if(toks.isEmpty()) {
|
||||||
|
return new ArrayList<>().stream();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var fst = toks.getFirst();
|
||||||
|
if (cond.apply(fst)) {
|
||||||
|
var newToks = List.copyOf(toks.subList(1, toks.size()));
|
||||||
|
this.getContent(
|
||||||
|
succeed(fst)
|
||||||
|
.apply().map(x -> x.apply(newToks))
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
Executable
+27
@@ -0,0 +1,27 @@
|
|||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class Pair<T, U> {
|
||||||
|
T a;
|
||||||
|
U b;
|
||||||
|
|
||||||
|
public Pair() { }
|
||||||
|
public Pair(T a, U b) {
|
||||||
|
System.out.println("Pair a; " + a + " b: " + b);
|
||||||
|
this.a = a;
|
||||||
|
this.b = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T fst () {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
public U snd () {
|
||||||
|
System.out.println("snd b: " + b);
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "Pair<"+a.toString()+","+b.toString()+">";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
import java.util.stream.Stream;
|
||||||
|
//import java.util.stream.IntStream;
|
||||||
|
//import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import java.lang.System;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.lang.Character;
|
||||||
|
import java.lang.String;
|
||||||
|
import java.lang.Boolean;
|
||||||
|
import java.lang.Integer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
//import java.util.function.IntFunction;
|
||||||
|
|
||||||
|
import Pair;
|
||||||
|
|
||||||
|
|
||||||
|
public class Parser {
|
||||||
|
|
||||||
|
|
||||||
|
strToList(s) {
|
||||||
|
var al;
|
||||||
|
al = new ArrayList<>();
|
||||||
|
var i = 0;
|
||||||
|
while (i < s.length()) {
|
||||||
|
al.add(s.charAt(i));
|
||||||
|
i=i+1;
|
||||||
|
}
|
||||||
|
return al;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
|
||||||
|
parser(p, inp) {
|
||||||
|
return p.map(y -> y.apply(
|
||||||
|
strToList(inp)//chars().mapToObj(c -> (Character) c)
|
||||||
|
//.toList()
|
||||||
|
))
|
||||||
|
|
||||||
|
//.flatMap(x -> x)
|
||||||
|
|
||||||
|
//.filter(x -> x.snd().isEmpty())
|
||||||
|
;
|
||||||
|
/*
|
||||||
|
.findFirst()
|
||||||
|
.get()
|
||||||
|
.fst()
|
||||||
|
|
||||||
|
;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
satisfy(cond) {
|
||||||
|
return newToks -> failure().apply().map(x -> x.apply(newToks));
|
||||||
|
/*
|
||||||
|
return () -> Stream.of (toks -> {
|
||||||
|
if(toks.isEmpty()) {
|
||||||
|
return new ArrayList<>().stream();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var fst = toks.getFirst();
|
||||||
|
if (cond.apply(fst)) {
|
||||||
|
var newToks = List.copyOf(toks.subList(1, toks.size()));
|
||||||
|
this.getContent(
|
||||||
|
succeed(fst)
|
||||||
|
.apply().map(x -> x.apply(newToks))
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
@@ -1,14 +1,13 @@
|
|||||||
public sealed interface List<T> permits Cons, Empty {}
|
import Cons;
|
||||||
|
import Empty;
|
||||||
public record Cons<T>(T a, List<T> l) implements List<T> {}
|
import List;
|
||||||
public record Empty<T>() implements List<T> {}
|
import Pair;
|
||||||
public record Pair<T1, T2>(T1 a, T2 b) {}
|
|
||||||
|
|
||||||
public class PatternMatching {
|
public class PatternMatching {
|
||||||
public zip(Cons(x, xs), Cons(y, ys)) {
|
public zip(Cons(x, xs), Cons(y, ys)) {
|
||||||
return new Cons<>(new Pair<>(x, y), zip(xs, ys));
|
return new Cons<>(new Pair<>(x, y), zip(xs, ys));
|
||||||
}
|
}
|
||||||
public zip(Empty(), Empty()) { return new Empty<>(); }
|
public zip(Empty x, Empty y) { return new Empty<>(); }
|
||||||
|
|
||||||
/*public zip(Empty x, Cons y) { return new Empty(); }
|
/*public zip(Empty x, Cons y) { return new Empty(); }
|
||||||
public zip(Cons x, Empty y) { return new Empty(); }
|
public zip(Cons x, Empty y) { return new Empty(); }
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import java.lang.Boolean;
|
import java.lang.Boolean;
|
||||||
import java.lang.Object;
|
import java.lang.Object;
|
||||||
|
|
||||||
public sealed interface List<T> permits Cons, Empty {}
|
sealed interface List<T> permits Cons, Empty {}
|
||||||
|
|
||||||
public record Cons<T>(T a, List<T> l) implements List<T> {}
|
public record Cons<T>(T a, List<T> l) implements List<T> {}
|
||||||
public record Empty<T>() implements List<T> {}
|
public record Empty<T>() implements List<T> {}
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
import java.lang.Integer;
|
|
||||||
import java.lang.Number;
|
|
||||||
|
|
||||||
public record R(Number n) {}
|
|
||||||
|
|
||||||
public class PatternMatchingSpecificity {
|
|
||||||
public m(R(Number n)) { return 0; }
|
|
||||||
public m(R(Integer i)) { return 1; }
|
|
||||||
}
|
|
||||||
@@ -1499,13 +1499,12 @@ public class Codegen {
|
|||||||
state.exitScope();
|
state.exitScope();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void extractField(State state, TargetType ret, TargetType type, int i, ClassOrInterface clazz) {
|
private void extractField(State state, TargetType type, int i, ClassOrInterface clazz) {
|
||||||
if (i >= clazz.getFieldDecl().size())
|
if (i >= clazz.getFieldDecl().size())
|
||||||
throw new CodeGenException("Couldn't find suitable field accessor for '" + type.name() + "'");
|
throw new CodeGenException("Couldn't find suitable field accessor for '" + type.name() + "'");
|
||||||
var field = clazz.getFieldDecl().get(i);
|
var field = clazz.getFieldDecl().get(i);
|
||||||
var fieldType = converter.convert(field.getType());
|
var fieldType = converter.convert(field.getType());
|
||||||
state.mv.visitMethodInsn(INVOKEVIRTUAL, type.getInternalName(), field.getName(), "()" + fieldType.toDescriptor(), false);
|
state.mv.visitMethodInsn(INVOKEVIRTUAL, type.getInternalName(), field.getName(), "()" + fieldType.toDescriptor(), false);
|
||||||
if (ret != null) convertTo(state, fieldType, ret);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void bindPattern(State state, TargetType type, TargetPattern pat, Label start, int index, int depth) {
|
private void bindPattern(State state, TargetType type, TargetPattern pat, Label start, int index, int depth) {
|
||||||
@@ -1568,7 +1567,7 @@ public class Codegen {
|
|||||||
var subPattern = cp.subPatterns().get(i);
|
var subPattern = cp.subPatterns().get(i);
|
||||||
|
|
||||||
state.mv.visitInsn(DUP);
|
state.mv.visitInsn(DUP);
|
||||||
extractField(state, null, cp.type(), i, clazz);
|
extractField(state, cp.type(), i, clazz);
|
||||||
|
|
||||||
if (subPattern.type() instanceof TargetRefType || subPattern.type() instanceof TargetExtendsWildcard) {
|
if (subPattern.type() instanceof TargetRefType || subPattern.type() instanceof TargetExtendsWildcard) {
|
||||||
state.mv.visitInsn(DUP);
|
state.mv.visitInsn(DUP);
|
||||||
@@ -1670,7 +1669,7 @@ public class Codegen {
|
|||||||
if (i < cp.subPatterns().size() - 1)
|
if (i < cp.subPatterns().size() - 1)
|
||||||
state.mv.visitInsn(DUP);
|
state.mv.visitInsn(DUP);
|
||||||
|
|
||||||
extractField(state, subPattern.type(), cp.type(), i, clazz);
|
extractField(state, cp.type(), i, clazz);
|
||||||
if (subPattern.type() instanceof TargetRefType)
|
if (subPattern.type() instanceof TargetRefType)
|
||||||
state.mv.visitTypeInsn(CHECKCAST, subPattern.type().getInternalName());
|
state.mv.visitTypeInsn(CHECKCAST, subPattern.type().getInternalName());
|
||||||
offset = state.createVariable(subPattern.name(), subPattern.type()).index;
|
offset = state.createVariable(subPattern.name(), subPattern.type()).index;
|
||||||
|
|||||||
@@ -20,11 +20,14 @@ import de.dhbwstuttgart.server.SocketFuture;
|
|||||||
import de.dhbwstuttgart.server.packet.SetAutoclosePacket;
|
import de.dhbwstuttgart.server.packet.SetAutoclosePacket;
|
||||||
import de.dhbwstuttgart.server.packet.UnifyRequestPacket;
|
import de.dhbwstuttgart.server.packet.UnifyRequestPacket;
|
||||||
import de.dhbwstuttgart.server.packet.UnifyResultPacket;
|
import de.dhbwstuttgart.server.packet.UnifyResultPacket;
|
||||||
import de.dhbwstuttgart.syntaxtree.*;
|
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.GenericTypeVar;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.Method;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.ParameterList;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.SourceFile;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.GenericDeclarationList;
|
||||||
import de.dhbwstuttgart.syntaxtree.factory.ASTFactory;
|
import de.dhbwstuttgart.syntaxtree.factory.ASTFactory;
|
||||||
import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory;
|
import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory;
|
||||||
import de.dhbwstuttgart.syntaxtree.statement.Block;
|
|
||||||
import de.dhbwstuttgart.syntaxtree.statement.Statement;
|
|
||||||
import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType;
|
import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType;
|
||||||
import de.dhbwstuttgart.syntaxtree.type.GenericRefType;
|
import de.dhbwstuttgart.syntaxtree.type.GenericRefType;
|
||||||
import de.dhbwstuttgart.syntaxtree.type.RefType;
|
import de.dhbwstuttgart.syntaxtree.type.RefType;
|
||||||
@@ -32,12 +35,9 @@ import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
|||||||
import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType;
|
import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType;
|
||||||
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
|
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
|
||||||
import de.dhbwstuttgart.syntaxtree.type.TypeVisitor;
|
import de.dhbwstuttgart.syntaxtree.type.TypeVisitor;
|
||||||
import de.dhbwstuttgart.syntaxtree.type.Void;
|
|
||||||
import de.dhbwstuttgart.syntaxtree.visual.ASTTypePrinter;
|
import de.dhbwstuttgart.syntaxtree.visual.ASTTypePrinter;
|
||||||
import de.dhbwstuttgart.target.generate.ASTToTargetAST;
|
import de.dhbwstuttgart.target.generate.ASTToTargetAST;
|
||||||
import de.dhbwstuttgart.target.generate.GenericsResult;
|
import de.dhbwstuttgart.target.generate.GenericsResult;
|
||||||
import de.dhbwstuttgart.target.tree.*;
|
|
||||||
import de.dhbwstuttgart.target.tree.type.*;
|
|
||||||
import de.dhbwstuttgart.typeinference.constraints.Constraint;
|
import de.dhbwstuttgart.typeinference.constraints.Constraint;
|
||||||
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
|
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
|
||||||
import de.dhbwstuttgart.typeinference.constraints.Pair;
|
import de.dhbwstuttgart.typeinference.constraints.Pair;
|
||||||
@@ -62,7 +62,6 @@ import de.dhbwstuttgart.typeinference.unify.UnifyTaskModel;
|
|||||||
|
|
||||||
import de.dhbwstuttgart.util.Logger;
|
import de.dhbwstuttgart.util.Logger;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.lang.Record;
|
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.sql.Array;
|
import java.sql.Array;
|
||||||
@@ -83,9 +82,7 @@ public class JavaTXCompiler {
|
|||||||
// public static JavaTXCompiler INSTANCE;
|
// public static JavaTXCompiler INSTANCE;
|
||||||
final CompilationEnvironment environment;
|
final CompilationEnvironment environment;
|
||||||
Boolean resultmodel = true;
|
Boolean resultmodel = true;
|
||||||
|
public final Map<File, SourceFile> sourceFiles = new HashMap<>();
|
||||||
private final List<File> sources;
|
|
||||||
public final Map<File, SourceFile> sourceFiles = new LinkedHashMap<>();
|
|
||||||
public final Set<JavaClassName> input = new HashSet<>();
|
public final Set<JavaClassName> input = new HashSet<>();
|
||||||
|
|
||||||
public volatile UnifyTaskModel usedTasks = new UnifyTaskModel();
|
public volatile UnifyTaskModel usedTasks = new UnifyTaskModel();
|
||||||
@@ -127,11 +124,7 @@ public class JavaTXCompiler {
|
|||||||
environment = new CompilationEnvironment(sources, classLoader);
|
environment = new CompilationEnvironment(sources, classLoader);
|
||||||
classPath = path;
|
classPath = path;
|
||||||
this.outputPath = outputPath;
|
this.outputPath = outputPath;
|
||||||
this.sources = sources;
|
|
||||||
// INSTANCE = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<SourceFileContext> generateSources(List<File> sources) throws IOException, ClassNotFoundException {
|
|
||||||
// TODO This should maybe be moved elsewhere
|
// TODO This should maybe be moved elsewhere
|
||||||
var treeList = new ArrayList<SourceFileContext>(sources.size());
|
var treeList = new ArrayList<SourceFileContext>(sources.size());
|
||||||
for (var s : sources) {
|
for (var s : sources) {
|
||||||
@@ -161,7 +154,11 @@ public class JavaTXCompiler {
|
|||||||
input.add(classRegistry.getName(className));
|
input.add(classRegistry.getName(className));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return treeList;
|
|
||||||
|
for (var i = 0; i < sources.size(); i++) {
|
||||||
|
parse(treeList.get(i), sources.get(i));
|
||||||
|
}
|
||||||
|
// INSTANCE = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addSourceFile(File file, SourceFile sf) {
|
private void addSourceFile(File file, SourceFile sf) {
|
||||||
@@ -689,7 +686,7 @@ public class JavaTXCompiler {
|
|||||||
|
|
||||||
public final JavaClassRegistry classRegistry = new JavaClassRegistry();
|
public final JavaClassRegistry classRegistry = new JavaClassRegistry();
|
||||||
|
|
||||||
private void parse(SourceFileContext tree, File sourceFile) throws IOException, ClassNotFoundException {
|
private void parse(SourceFileContext tree, File sourceFile) throws IOException, java.lang.ClassNotFoundException {
|
||||||
SyntaxTreeGenerator generator = new SyntaxTreeGenerator(this, classRegistry, new GenericsRegistry(null), sourceFile.getName());
|
SyntaxTreeGenerator generator = new SyntaxTreeGenerator(this, classRegistry, new GenericsRegistry(null), sourceFile.getName());
|
||||||
environment.addClassesToRegistry(classRegistry, tree, sourceFile, this);
|
environment.addClassesToRegistry(classRegistry, tree, sourceFile, this);
|
||||||
var classes = new ArrayList<ClassOrInterface>();
|
var classes = new ArrayList<ClassOrInterface>();
|
||||||
@@ -700,18 +697,8 @@ public class JavaTXCompiler {
|
|||||||
sf.imports.addAll(generator.imports);
|
sf.imports.addAll(generator.imports);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void parseAll() throws IOException, ClassNotFoundException {
|
|
||||||
var treeList = generateSources(sources);
|
|
||||||
for (var i = 0; i < sources.size(); i++) {
|
|
||||||
parse(treeList.get(i), sources.get(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void generateBytecode() throws ClassNotFoundException, IOException {
|
public void generateBytecode() throws ClassNotFoundException, IOException {
|
||||||
// The compiler has two modes, one is to infer all files together and the other one is to do them in sequence
|
|
||||||
if (inferTogether) {
|
if (inferTogether) {
|
||||||
parseAll();
|
|
||||||
|
|
||||||
var files = sourceFiles.keySet().stream().toList();
|
var files = sourceFiles.keySet().stream().toList();
|
||||||
var typeinferenceResult = this.typeInference(files);
|
var typeinferenceResult = this.typeInference(files);
|
||||||
for (var file : files) {
|
for (var file : files) {
|
||||||
@@ -722,11 +709,7 @@ public class JavaTXCompiler {
|
|||||||
writeClassFile(classes, outputPath == null ? file.getParentFile() : outputPath, outputPath == null);
|
writeClassFile(classes, outputPath == null ? file.getParentFile() : outputPath, outputPath == null);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var treeList = generateSources(sources);
|
for (var file : sourceFiles.keySet()) {
|
||||||
for (var i = 0; i < sources.size(); i++) {
|
|
||||||
var file = sources.get(i);
|
|
||||||
parse(treeList.get(i), file);
|
|
||||||
|
|
||||||
var sf = sourceFiles.get(file);
|
var sf = sourceFiles.get(file);
|
||||||
if (sf.isGenerated()) continue;
|
if (sf.isGenerated()) continue;
|
||||||
var classes = generateBytecode(file);
|
var classes = generateBytecode(file);
|
||||||
@@ -736,7 +719,7 @@ public class JavaTXCompiler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<JavaClassName, byte[]> generateBytecode(File sourceFile) throws ClassNotFoundException, IOException {
|
public Map<JavaClassName, byte[]> generateBytecode(File sourceFile) throws ClassNotFoundException, IOException {
|
||||||
var sf = sourceFiles.get(sourceFile);
|
var sf = sourceFiles.get(sourceFile);
|
||||||
if (sf.isGenerated()) return null;
|
if (sf.isGenerated()) return null;
|
||||||
List<ResultSet> typeinferenceResult = this.typeInference(sourceFile);
|
List<ResultSet> typeinferenceResult = this.typeInference(sourceFile);
|
||||||
@@ -770,91 +753,11 @@ public class JavaTXCompiler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Maybe move this elsewhere it doesn't really belong here
|
|
||||||
private static RefTypeOrTPHOrWildcardOrGeneric toRefType(TargetType type) {
|
|
||||||
return switch(type) {
|
|
||||||
case TargetExtendsWildcard targetExtendsWildcard ->
|
|
||||||
new ExtendsWildcardType(toRefType(targetExtendsWildcard.innerType()), new NullToken());
|
|
||||||
case TargetSuperWildcard targetSuperWildcard ->
|
|
||||||
new SuperWildcardType(toRefType(targetSuperWildcard.innerType()), new NullToken());
|
|
||||||
case TargetGenericType targetGenericType -> new GenericRefType(targetGenericType.name(), new NullToken());
|
|
||||||
case TargetPrimitiveType targetPrimitiveType -> toRefType(TargetType.toWrapper(targetPrimitiveType));
|
|
||||||
case TargetSpecializedType targetSpecializedType ->
|
|
||||||
new RefType(new JavaClassName(targetSpecializedType.name()),
|
|
||||||
targetSpecializedType.params().stream().map(JavaTXCompiler::toRefType).toList(), new NullToken()
|
|
||||||
);
|
|
||||||
case null -> new Void(new NullToken());
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ParameterList toParameterList(List<MethodParameter> params) {
|
|
||||||
return new ParameterList(params.stream().map(mp
|
|
||||||
-> (Pattern) new FormalParameter(mp.pattern().name(), toRefType(mp.pattern().type()), new NullToken())).toList(),
|
|
||||||
new NullToken()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static GenericDeclarationList toGenerics(Set<TargetGeneric> generics) {
|
|
||||||
return new GenericDeclarationList(
|
|
||||||
generics.stream().map(g
|
|
||||||
-> new GenericTypeVar(g.name(), List.of(toRefType(g.bound())), new NullToken(), new NullToken())
|
|
||||||
).toList(), new NullToken()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This writes back the compiled target structure into the loadedClasses map so that it can be used
|
|
||||||
* as an input in further processing
|
|
||||||
* @param target
|
|
||||||
*/
|
|
||||||
private void writeBackToClass(TargetStructure target) {
|
|
||||||
var fielddecl = new ArrayList<Field>();
|
|
||||||
for (var field : target.fields()) {
|
|
||||||
fielddecl.add(new Field(field.name(), toRefType(field.type()), field.access(), new NullToken()));
|
|
||||||
}
|
|
||||||
|
|
||||||
var methods = new ArrayList<Method>();
|
|
||||||
for (var method : target.methods()) {
|
|
||||||
methods.add(new Method(method.access(), method.name(), toRefType(method.signature().returnType()),
|
|
||||||
toParameterList(method.signature().parameters()), new Block(new ArrayList<>(), new NullToken()), toGenerics(method.signature().generics()), new NullToken())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
var constructors = new ArrayList<Constructor>();
|
|
||||||
for (var ctor : target.constructors()) {
|
|
||||||
constructors.add(new Constructor(ctor.access(), target.getName(), new RefType(target.qualifiedName(), new NullToken()),
|
|
||||||
toParameterList(ctor.parameters()), new Block(new ArrayList<>(), new NullToken()), toGenerics(ctor.generics()), new NullToken())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
var generics = new GenericDeclarationList(toGenerics(target.generics()), new NullToken());
|
|
||||||
var superClass = (RefType) toRefType(target.superType());
|
|
||||||
var isInterface = target instanceof TargetInterface;
|
|
||||||
var isFunctionalInterface = false; // TODO We might actually want to generate those
|
|
||||||
var implementedInterfaces = target.implementingInterfaces().stream()
|
|
||||||
.map(t -> (RefType) toRefType(t)).toList();
|
|
||||||
var permittedSubtypes = List.<RefType>of();
|
|
||||||
if (target instanceof TargetInterface tinf) {
|
|
||||||
permittedSubtypes = tinf.permittedSubtypes().stream().map(t -> (RefType) toRefType(t)).toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
var clazz = new ClassOrInterface(
|
|
||||||
target.modifiers(), target.qualifiedName(),
|
|
||||||
fielddecl, Optional.empty(), Optional.empty(),
|
|
||||||
methods, constructors, generics, superClass,
|
|
||||||
isInterface, isFunctionalInterface, implementedInterfaces,
|
|
||||||
permittedSubtypes, new NullToken(), ""
|
|
||||||
);
|
|
||||||
loadedClasses.put(target.qualifiedName(), clazz);
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized Map<JavaClassName, byte[]> generateBytecode(SourceFile sf, List<ResultSet> typeInferenceResult) {
|
public synchronized Map<JavaClassName, byte[]> generateBytecode(SourceFile sf, List<ResultSet> typeInferenceResult) {
|
||||||
var converter = new ASTToTargetAST(this, typeInferenceResult, sf, classLoader);
|
var converter = new ASTToTargetAST(this, typeInferenceResult, sf, classLoader);
|
||||||
var generatedClasses = new HashMap<JavaClassName, byte[]>();
|
var generatedClasses = new HashMap<JavaClassName, byte[]>();
|
||||||
for (var clazz : sf.getClasses()) {
|
for (var clazz : sf.getClasses()) {
|
||||||
var target = converter.convert(clazz);
|
var codegen = new Codegen(converter.convert(clazz), this, converter);
|
||||||
writeBackToClass(target);
|
|
||||||
var codegen = new Codegen(target, this, converter);
|
|
||||||
var code = codegen.generate();
|
var code = codegen.generate();
|
||||||
generatedClasses.put(clazz.getClassName(), code);
|
generatedClasses.put(clazz.getClassName(), code);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,11 +58,14 @@ public class LanguageServerInterface {
|
|||||||
var file = path.toFile();
|
var file = path.toFile();
|
||||||
Files.createDirectories(path.getParent().resolve("out"));
|
Files.createDirectories(path.getParent().resolve("out"));
|
||||||
var compiler = new JavaTXCompiler(List.of(file), List.of(path.getParent().toFile()), path.getParent().resolve("out").toFile(), false);
|
var compiler = new JavaTXCompiler(List.of(file), List.of(path.getParent().toFile()), path.getParent().resolve("out").toFile(), false);
|
||||||
compiler.generateBytecode();
|
|
||||||
|
|
||||||
var parsedSource = compiler.sourceFiles.get(file);
|
var parsedSource = compiler.sourceFiles.get(file);
|
||||||
var tiResults = compiler.typeInference(file);
|
var tiResults = compiler.typeInference(file);
|
||||||
|
|
||||||
|
Map<JavaClassName, byte[]> bytecode = compiler.generateBytecode(parsedSource, tiResults);
|
||||||
|
Files.createDirectories(path.getParent().resolve("out"));
|
||||||
|
compiler.writeClassFile(bytecode, path.getParent().resolve("out").toFile(), false);
|
||||||
|
|
||||||
return new LanguageServerTransferObject(tiResults, parsedSource, "", compiler.getGeneratedGenerics());
|
return new LanguageServerTransferObject(tiResults, parsedSource, "", compiler.getGeneratedGenerics());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e.getMessage(), e);
|
throw new RuntimeException(e.getMessage(), e);
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
package de.dhbwstuttgart.target.generate;
|
package de.dhbwstuttgart.target.generate;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import de.dhbwstuttgart.bytecode.FunNGenerator;
|
import de.dhbwstuttgart.bytecode.FunNGenerator;
|
||||||
import de.dhbwstuttgart.core.JavaTXCompiler;
|
import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||||
import de.dhbwstuttgart.environment.IByteArrayClassLoader;
|
import de.dhbwstuttgart.environment.IByteArrayClassLoader;
|
||||||
import de.dhbwstuttgart.exceptions.DebugException;
|
import de.dhbwstuttgart.exceptions.DebugException;
|
||||||
import de.dhbwstuttgart.exceptions.NotImplementedException;
|
|
||||||
import de.dhbwstuttgart.parser.NullToken;
|
import de.dhbwstuttgart.parser.NullToken;
|
||||||
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||||
import de.dhbwstuttgart.syntaxtree.*;
|
import de.dhbwstuttgart.syntaxtree.*;
|
||||||
@@ -13,20 +11,17 @@ import de.dhbwstuttgart.syntaxtree.Record;
|
|||||||
import de.dhbwstuttgart.syntaxtree.factory.ASTFactory;
|
import de.dhbwstuttgart.syntaxtree.factory.ASTFactory;
|
||||||
import de.dhbwstuttgart.syntaxtree.statement.*;
|
import de.dhbwstuttgart.syntaxtree.statement.*;
|
||||||
import de.dhbwstuttgart.syntaxtree.type.*;
|
import de.dhbwstuttgart.syntaxtree.type.*;
|
||||||
import de.dhbwstuttgart.target.Target;
|
import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.visual.OutputGenerator;
|
||||||
import de.dhbwstuttgart.target.tree.*;
|
import de.dhbwstuttgart.target.tree.*;
|
||||||
import de.dhbwstuttgart.target.tree.expression.*;
|
import de.dhbwstuttgart.target.tree.expression.*;
|
||||||
import de.dhbwstuttgart.target.tree.type.*;
|
import de.dhbwstuttgart.target.tree.type.*;
|
||||||
import de.dhbwstuttgart.typeinference.result.*;
|
import de.dhbwstuttgart.typeinference.result.*;
|
||||||
import de.dhbwstuttgart.typeinference.unify.MartelliMontanariUnify;
|
|
||||||
import de.dhbwstuttgart.typeinference.unify.model.*;
|
|
||||||
|
|
||||||
import javax.swing.text.html.Option;
|
import java.lang.annotation.Target;
|
||||||
import java.sql.Array;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import java.util.stream.StreamSupport;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author dholle
|
* @author dholle
|
||||||
@@ -66,7 +61,7 @@ public class ASTToTargetAST {
|
|||||||
return converter.result;
|
return converter.result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public record Generics(IGenerics javaGenerics, IGenerics txGenerics) {
|
public record Generics(JavaGenerics javaGenerics, TxGenerics txGenerics) {
|
||||||
public Generics(JavaTXCompiler compiler, ResultSet set) {
|
public Generics(JavaTXCompiler compiler, ResultSet set) {
|
||||||
this(new JavaGenerics(compiler, set), new TxGenerics(compiler, set));
|
this(new JavaGenerics(compiler, set), new TxGenerics(compiler, set));
|
||||||
}
|
}
|
||||||
@@ -161,190 +156,190 @@ public class ASTToTargetAST {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static UnifyType toUnifyType(TargetType a) {
|
// This finds a common sealed interface type to group together methods that use different records
|
||||||
return switch(a) {
|
// This function should do matching or unification
|
||||||
case TargetExtendsWildcard targetExtendsWildcard -> new ExtendsType(toUnifyType(targetExtendsWildcard.innerType()));
|
private List<ClassOrInterface> commonSuperInterfaceTypes(TargetType a, TargetType b) {
|
||||||
case TargetSuperWildcard targetSuperWildcard -> new SuperType(toUnifyType(targetSuperWildcard.innerType()));
|
if (a instanceof TargetGenericType && b instanceof TargetGenericType) return List.of(ASTFactory.createObjectClass());
|
||||||
case TargetGenericType targetGenericType -> new PlaceholderType(targetGenericType.name(), JavaTXCompiler.defaultClientPlaceholderRegistry);
|
if (a instanceof TargetRefType ta && b instanceof TargetGenericType)
|
||||||
case TargetPrimitiveType _ -> throw new NotImplementedException();
|
return List.of(compiler.getClass(new JavaClassName(ta.name())));
|
||||||
case TargetFunNType targetFunNType -> FunNType.getFunNType(new TypeParams(targetFunNType.params().stream().map(ASTToTargetAST::toUnifyType).toList()));
|
if (b instanceof TargetRefType tb && a instanceof TargetGenericType)
|
||||||
case TargetRefType targetRefType -> new ReferenceType(targetRefType.name(), new TypeParams(targetRefType.params().stream().map(ASTToTargetAST::toUnifyType).toList()));
|
return List.of(compiler.getClass(new JavaClassName(tb.name())));
|
||||||
};
|
|
||||||
|
if (a instanceof TargetRefType ta && b instanceof TargetRefType tb) {
|
||||||
|
var res = new HashSet<ClassOrInterface>();
|
||||||
|
|
||||||
|
var cla = compiler.getClass(new JavaClassName(ta.name()));
|
||||||
|
var clb = compiler.getClass(new JavaClassName(tb.name()));
|
||||||
|
|
||||||
|
if (cla.equals(clb)) return List.of(cla);
|
||||||
|
|
||||||
|
while (!cla.equals(ASTFactory.createObjectClass())) {
|
||||||
|
var clb2 = clb;
|
||||||
|
while (!clb2.equals(ASTFactory.createObjectClass())) {
|
||||||
|
for (var intfa : cla.getSuperInterfaces()) {
|
||||||
|
for (var intfb : clb.getSuperInterfaces()) {
|
||||||
|
if (intfa.equals(intfb)) {
|
||||||
|
var clintf = compiler.getClass(intfa.getName());
|
||||||
|
if (clintf.isSealed()) {
|
||||||
|
res.add(clintf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clb2 = compiler.getClass(clb2.getSuperClass().getName());
|
||||||
|
}
|
||||||
|
cla = compiler.getClass(cla.getSuperClass().getName());
|
||||||
|
}
|
||||||
|
return res.stream().toList();
|
||||||
|
}
|
||||||
|
return List.of();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TargetType toTargetType(UnifyType a) {
|
private boolean canCombine(Signature m1, Signature m2) {
|
||||||
return switch (a) {
|
var pl1 = m1.java.parameters();
|
||||||
case ExtendsType extendType -> new TargetExtendsWildcard(toTargetType(extendType.getExtendedType()));
|
var pl2 = m2.java.parameters();
|
||||||
case SuperType superType -> new TargetSuperWildcard(toTargetType(superType.getSuperedType()));
|
if (pl1.size() != pl2.size()) return false;
|
||||||
case PlaceholderType placeholderType -> new TargetGenericType(placeholderType.getName());
|
if (pl1.isEmpty()) return false;
|
||||||
case FunNType funNType -> TargetFunNType.fromParams(StreamSupport.stream(funNType.getTypeParams().spliterator(), false).map(ASTToTargetAST::toTargetType).toList(), 1); // FIXME How does this work with Fun0??
|
for (var i = 0; i < pl1.size(); i++) {
|
||||||
case ReferenceType referenceType -> new TargetRefType(referenceType.getName(), StreamSupport.stream(referenceType.getTypeParams().spliterator(), false).map(ASTToTargetAST::toTargetType).toList());
|
var p1 = pl1.get(i).pattern();
|
||||||
default -> throw new NotImplementedException();
|
var p2 = pl2.get(i).pattern();
|
||||||
};
|
// TPH <> RefType sind nicht unterscheidbar
|
||||||
}
|
if (p1.type() instanceof TargetGenericType || p2.type() instanceof TargetGenericType) continue;
|
||||||
|
// Pattern(X) <> Pattern(Y) ist nicht unterscheidbar
|
||||||
private static boolean typesStrictlyEqual(List<TargetType> a, List<TargetType> b) {
|
if (p1 instanceof TargetComplexPattern pc1 && p2 instanceof TargetComplexPattern pc2 &&
|
||||||
if (a.size() != b.size()) return false;
|
pc1.type().equals(pc2.type())) continue;
|
||||||
for (var i = 0; i < a.size(); i++) {
|
if (!p1.equals(p2)) return false;
|
||||||
if (!typesStrictlyEqual(a.get(i), b.get(i))) return false;
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO This should be moved elsewhere
|
private record Combination(MethodWithTphs a, MethodWithTphs b) {
|
||||||
private static boolean typesStrictlyEqual(TargetType a, TargetType b) {
|
@Override
|
||||||
if (a instanceof TargetRefType ta && b instanceof TargetRefType tb) {
|
public boolean equals(Object o) {
|
||||||
if (!Objects.equals(ta.name(), tb.name())) return false;
|
if (!(o instanceof Combination(MethodWithTphs a1, MethodWithTphs b1))) return false;
|
||||||
if (ta.params().size() != tb.params().size()) return false;
|
return this.a.equals(a1) && this.b.equals(b1) ||
|
||||||
for (var i = 0; i < ta.params().size(); i++) {
|
this.a.equals(b1) && this.b.equals(a1);
|
||||||
if (!typesStrictlyEqual(ta.params().get(i), tb.params().get(i)))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// Generics are considered equal
|
|
||||||
if (a instanceof TargetGenericType && b instanceof TargetGenericType)
|
|
||||||
return true;
|
|
||||||
return Objects.equals(a, b);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Optional<TargetType> unify(TargetType a, TargetType b) {
|
|
||||||
if (typesStrictlyEqual(a, b)) return Optional.of(a);
|
|
||||||
var unify = new MartelliMontanariUnify();
|
|
||||||
var ua = toUnifyType(a);
|
|
||||||
var unifier = unify.unify(Set.of(ua, toUnifyType(b)));
|
|
||||||
if (unifier.isEmpty()) return Optional.empty();
|
|
||||||
return Optional.of(toTargetType(unifier.get().apply(ua)));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Optional<List<MethodParameter>> unify(List<MethodParameter> a, List<MethodParameter> b) {
|
|
||||||
if (a.size() != b.size()) return Optional.empty();
|
|
||||||
var result = new ArrayList<MethodParameter>();
|
|
||||||
for (var i = 0; i < a.size(); i++) {
|
|
||||||
var u = unify(a.get(i).pattern().type(), b.get(i).pattern().type());
|
|
||||||
if (u.isEmpty()) return Optional.empty();
|
|
||||||
// Strip off patterns, we don't need them for merged methods, they do a switch case
|
|
||||||
result.add(new MethodParameter(u.get(), a.get(i).pattern().name()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Optional.of(result);
|
@Override
|
||||||
}
|
public int hashCode() {
|
||||||
|
return Objects.hashCode(a) + Objects.hashCode(b);
|
||||||
private static Set<String> findUsedGenerics(TargetType type) {
|
|
||||||
if (type instanceof TargetSpecializedType tspec) {
|
|
||||||
return tspec.params().stream().map(ASTToTargetAST::findUsedGenerics).flatMap(Set::stream).collect(Collectors.toSet());
|
|
||||||
} else if (type instanceof TargetGenericType(String name)) {
|
|
||||||
var set = new HashSet<String>();
|
|
||||||
set.add(name);
|
|
||||||
return set;
|
|
||||||
}
|
|
||||||
return new HashSet<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
// When unifying types we need to keep the generics that are still used in the signature
|
|
||||||
// This is done in an extra step after all generics have been combined into one list
|
|
||||||
private static void correctGenerics(TargetMethod.Signature signature, List<TargetGeneric> generics) {
|
|
||||||
var outGenerics = signature.generics();
|
|
||||||
outGenerics.addAll(generics);
|
|
||||||
var foundGenerics = signature.parameters().stream().map(p -> findUsedGenerics(p.pattern().type()))
|
|
||||||
.flatMap(Set::stream)
|
|
||||||
.collect(Collectors.toSet());
|
|
||||||
foundGenerics.addAll(findUsedGenerics(signature.returnType()));
|
|
||||||
|
|
||||||
for (var generic : new HashSet<>(outGenerics)) {
|
|
||||||
if (!foundGenerics.contains(generic.name())) outGenerics.remove(generic);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Optional<TargetMethod.Signature> unify(TargetMethod.Signature a, TargetMethod.Signature b) {
|
private List<List<MethodWithTphs>> groupOverloads(ClassOrInterface input, List<Method> methods) {
|
||||||
var returnType = unify(a.returnType(), b.returnType());
|
var mapOfTargetMethods = new HashMap<Generics, MethodWithTphs[]>();
|
||||||
if (returnType.isEmpty()) return Optional.empty();
|
for (var gen : all) {
|
||||||
var res = unify(a.parameters(), b.parameters());
|
mapOfTargetMethods.put(gen, new MethodWithTphs[methods.size()]);
|
||||||
if (res.isEmpty()) return Optional.empty();
|
|
||||||
var generics = new ArrayList<>(a.generics());
|
|
||||||
generics.addAll(b.generics());
|
|
||||||
var signature = new TargetMethod.Signature(new HashSet<>(), res.get(), returnType.get());
|
|
||||||
correctGenerics(signature, generics);
|
|
||||||
return Optional.of(signature);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Optional<MethodGroup> unify(MethodGroup a, MethodGroup b) {
|
|
||||||
var junified = unify(a.signature.java, b.signature.java);
|
|
||||||
if (junified.isEmpty()) return Optional.empty();
|
|
||||||
var txunified = unify(a.signature.tx, b.signature.tx);
|
|
||||||
|
|
||||||
var unifiedSignature = new Signature(junified.get(), txunified.orElseGet(junified::get), a.signature().generics);
|
|
||||||
|
|
||||||
var concat = new HashSet<>(a.methods);
|
|
||||||
concat.addAll(b.methods);
|
|
||||||
return Optional.of(new MethodGroup(unifiedSignature, concat));
|
|
||||||
}
|
|
||||||
|
|
||||||
private record NameAndParameters(String name, int parameters) {}
|
|
||||||
|
|
||||||
private List<List<Method>> groupMethods(ClassOrInterface input, List<Method> methods) {
|
|
||||||
var groups = new HashMap<NameAndParameters, List<Method>>();
|
|
||||||
for (var m : methods) {
|
|
||||||
var nameAndParameters = new NameAndParameters(m.name, m.getParameterList().getFormalparalist().size());
|
|
||||||
var l = groups.getOrDefault(nameAndParameters, new ArrayList<>());
|
|
||||||
l.add(m);
|
|
||||||
groups.put(nameAndParameters, l);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return groups.values().stream().toList();
|
for (var i = 0; i < methods.size(); i++) {
|
||||||
}
|
var method = methods.get(i);
|
||||||
|
|
||||||
private Set<MethodGroup> groupOverloads(ClassOrInterface input, List<Method> methods) {
|
|
||||||
var a = new HashSet<MethodGroup>();
|
|
||||||
|
|
||||||
for (Method method : methods) {
|
|
||||||
// Convert all methods
|
// Convert all methods
|
||||||
var methodsWithTphs = convert(input, method);
|
var methodsWithTphs = convert(input, method);
|
||||||
for (var m : methodsWithTphs) {
|
for (var m : methodsWithTphs) {
|
||||||
var mtph = new MethodWithTphs(m.method, m.generics, m.signature);
|
var resultMethods = mapOfTargetMethods.get(m.generics);
|
||||||
a.add(new MethodGroup(m.signature, Set.of(mtph)));
|
resultMethods[i] = new MethodWithTphs(m.method, m.generics, m.signature);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
System.out.println("============== INPUT ==============");
|
System.out.println("============== INPUT ==============");
|
||||||
for (var m : a) {
|
for (var m : mapOfTargetMethods.values()) {
|
||||||
System.out.println(m);
|
for (var v : m) if (v != null) System.out.println(v.signature.java.returnType() + " " + v.method.name + " " + v.signature.java().parameters());
|
||||||
|
System.out.println();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Algorithm
|
var allCombinations = new HashSet<Set<Combination>>();
|
||||||
|
// Combine methods based on their signature and position in the result set
|
||||||
|
for (var g1 : all) {
|
||||||
|
var resMeth1 = mapOfTargetMethods.get(g1);
|
||||||
|
for (var i = 0; i < methods.size(); i++) {
|
||||||
|
var m1 = resMeth1[i];
|
||||||
|
if (m1 == null) continue;
|
||||||
|
|
||||||
var R = new HashSet<MethodGroup>();
|
for (var g2 : all) {
|
||||||
var i = new HashSet<>(a);
|
if (g1 == g2) continue; // No need to combine the same method
|
||||||
|
var resMeth2 = mapOfTargetMethods.get(g2);
|
||||||
|
var m2 = resMeth2[i];
|
||||||
|
if (m2 == null) continue;
|
||||||
|
|
||||||
while (!i.isEmpty()) {
|
var combinations = new HashSet<Combination>();
|
||||||
var m = i.iterator().next();
|
|
||||||
i.remove(m);
|
if (canCombine(m1.signature, m2.signature)) {
|
||||||
R.add(m);
|
//System.out.println(" Combining " + m1.signature.java.getSignature() + " and " + m2.signature.java.getSignature());
|
||||||
var a1 = new HashSet<>(a);
|
combinations.add(new Combination(m1, m2));
|
||||||
for (var m1 : a1) {
|
for (var j = 0; j < methods.size(); j++) {
|
||||||
if (m1 != m) {
|
if (j == i) continue;
|
||||||
var u_opt = unify(m, m1);
|
var m3 = resMeth2[j];
|
||||||
if (u_opt.isPresent()) {
|
if (m3 == null) continue;
|
||||||
var u = u_opt.get();
|
var m4 = resMeth1[j];
|
||||||
//System.out.println("Unified " + m + " AND " + m1 + "\n\t" + u);
|
if (m4 == null) continue;
|
||||||
i.remove(m1);
|
combinations.add(new Combination(m4, m3));
|
||||||
R.remove(m);
|
//System.out.println("Also Combining " + m4.signature.java.getSignature() + " and " + m3.signature.java.getSignature());
|
||||||
R.remove(m1);
|
}
|
||||||
R.add(u);
|
} else {
|
||||||
a.add(u);
|
//System.out.println(" Not Combining " + m1.signature.java.getSignature() + " and " + m2.signature.java.getSignature());
|
||||||
} /*else {
|
}
|
||||||
System.out.println("Couldn't unify " + m + " AND " + m1);
|
if (!combinations.isEmpty()) allCombinations.add(combinations);
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
System.out.println("============== OUTPUT ==============");
|
if (allCombinations.isEmpty()) allCombinations.add(new HashSet<>());
|
||||||
for (var mg : R) {
|
|
||||||
System.out.println(mg.methods.size() + " " + mg);
|
// Combine back into output format
|
||||||
|
var r0 = new HashSet<Set<MethodWithTphs>>();
|
||||||
|
for (var combinations : allCombinations) {
|
||||||
|
var r1 = new HashSet<Set<MethodWithTphs>>();
|
||||||
|
// This is used to weed out duplicates
|
||||||
|
var uniqued = new HashSet<MethodWithTphs>();
|
||||||
|
// We go over all methods in the result
|
||||||
|
for (var g : all) for (var i = 0; i < methods.size(); i++) {
|
||||||
|
var r2 = new HashSet<MethodWithTphs>();
|
||||||
|
var m = mapOfTargetMethods.get(g)[i];
|
||||||
|
if (m == null) continue;
|
||||||
|
if (!uniqued.contains(m)) {
|
||||||
|
// Add the method to r2
|
||||||
|
r2.add(m);
|
||||||
|
uniqued.add(m);
|
||||||
|
} else continue;
|
||||||
|
// Find all combinations that contain the method and add them to the result
|
||||||
|
// if not filtered out by uniqued
|
||||||
|
for (var c : combinations) {
|
||||||
|
if (c.a.equals(m) || c.b.equals(m)) {
|
||||||
|
if (!uniqued.contains(c.a)) {
|
||||||
|
r2.add(c.a);
|
||||||
|
uniqued.add(c.a);
|
||||||
|
}
|
||||||
|
if (!uniqued.contains(c.b)) {
|
||||||
|
r2.add(c.b);
|
||||||
|
uniqued.add(c.b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
r1.add(r2);
|
||||||
|
}
|
||||||
|
outer: for (var s1 : r1) {
|
||||||
|
for (var s2 : new HashSet<>(r0)) {
|
||||||
|
if (s2.containsAll(s1)) {
|
||||||
|
continue outer;
|
||||||
|
} else if (s1.containsAll(s2)) {
|
||||||
|
r0.remove(s2);
|
||||||
|
r0.add(s1);
|
||||||
|
continue outer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
r0.add(s1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return R;
|
var result = r0.stream().map(l -> l.stream().toList()).toList();
|
||||||
|
|
||||||
|
//System.out.println("============== OUTPUT ==============");
|
||||||
|
//for (var l : result) {
|
||||||
|
// for (var m : l) System.out.println(m.method.name + " " + m.signature.java.getSignature());
|
||||||
|
// System.out.println();
|
||||||
|
//}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TargetStructure convert(ClassOrInterface input) {
|
public TargetStructure convert(ClassOrInterface input) {
|
||||||
@@ -378,36 +373,19 @@ public class ASTToTargetAST {
|
|||||||
var superInterfaces = input.getSuperInterfaces().stream().map(clazz -> convert(clazz, generics.javaGenerics, compiler)).toList();
|
var superInterfaces = input.getSuperInterfaces().stream().map(clazz -> convert(clazz, generics.javaGenerics, compiler)).toList();
|
||||||
var constructors = input.getConstructors().stream().map(constructor -> this.convert(input, constructor, finalFieldInitializer, generics)).flatMap(List::stream).toList();
|
var constructors = input.getConstructors().stream().map(constructor -> this.convert(input, constructor, finalFieldInitializer, generics)).flatMap(List::stream).toList();
|
||||||
var fields = input.getFieldDecl().stream().map(f -> convert(f, generics.javaGenerics)).toList();
|
var fields = input.getFieldDecl().stream().map(f -> convert(f, generics.javaGenerics)).toList();
|
||||||
var m0 = groupMethods(input, input.getMethods());
|
var methods = groupOverloads(input, input.getMethods()).stream().map(m -> generatePatternOverloads(input, m)).flatMap(List::stream)
|
||||||
|
.collect(Collectors.toSet()).stream().toList(); // Unique generated methods
|
||||||
var m1 = new ArrayList<TargetMethod>();
|
|
||||||
for (var group : m0) {
|
|
||||||
var overloads = groupOverloads(input, group);
|
|
||||||
// This contains the merged pattern overloads
|
|
||||||
var genMethods = new ArrayList<TargetMethod>();
|
|
||||||
for (var o : overloads) {
|
|
||||||
var pOverloads = generatePatternOverloads(input, o);
|
|
||||||
m1.addAll(pOverloads);
|
|
||||||
if (!pOverloads.isEmpty()) {
|
|
||||||
genMethods.add(pOverloads.getLast());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var bridge = generateBridgeMethod(input, genMethods);
|
|
||||||
bridge.map(m1::add);
|
|
||||||
}
|
|
||||||
var methods = new HashSet<>(m1).stream().toList();
|
|
||||||
|
|
||||||
TargetMethod staticConstructor = null;
|
TargetMethod staticConstructor = null;
|
||||||
if (input.getStaticInitializer().isPresent()) {
|
if (input.getStaticInitializer().isPresent()) {
|
||||||
var init = this.convert(input, input.getStaticInitializer().get()).stream().findFirst().orElseThrow();
|
var init = this.convert(input, input.getStaticInitializer().get()).stream().findFirst().orElseThrow();
|
||||||
staticConstructor = this.convert(init);
|
staticConstructor = this.convert(init, init.generics.javaGenerics);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input instanceof Record)
|
if (input instanceof Record)
|
||||||
return new TargetRecord(input.getModifiers(), input.getClassName(), javaGenerics, txGenerics, superInterfaces, constructors, staticConstructor, fields, methods);
|
return new TargetRecord(input.getModifiers(), input.getClassName(), javaGenerics, txGenerics, superInterfaces, constructors, staticConstructor, fields, methods);
|
||||||
else if (input.isInterface())
|
else if (input.isInterface())
|
||||||
return new TargetInterface(input.getModifiers(), input.getClassName(), javaGenerics, txGenerics, methods, superInterfaces, staticConstructor,
|
return new TargetInterface(input.getModifiers(), input.getClassName(), javaGenerics, txGenerics, methods, superInterfaces, staticConstructor);
|
||||||
input.getPermittedSubtypes().stream().map(t -> (TargetRefType) convert(t)).toList());
|
|
||||||
else return new TargetClass(input.getModifiers(), input.getClassName(), convert(input.getSuperClass(), generics.javaGenerics, compiler), javaGenerics, txGenerics, superInterfaces, constructors, staticConstructor, fields, methods);
|
else return new TargetClass(input.getModifiers(), input.getClassName(), convert(input.getSuperClass(), generics.javaGenerics, compiler), javaGenerics, txGenerics, superInterfaces, constructors, staticConstructor, fields, methods);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -503,31 +481,34 @@ public class ASTToTargetAST {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TargetExpression generateCall(TargetMethod method, List<TargetLocalVar> params, TargetType classType) {
|
private TargetType unwrap(TargetType type) {
|
||||||
var mParams = new ArrayList<TargetExpression>();
|
if (type instanceof TargetRefType ref) {
|
||||||
for (var i = 0; i < params.size(); i++) {
|
if (!ref.params().isEmpty()) return new TargetRefType(ref.name());
|
||||||
var tpe = method.signature().parameters().get(i).pattern().type();
|
|
||||||
mParams.add(new TargetLocalVar(tpe, params.get(i).name()));
|
|
||||||
}
|
}
|
||||||
TargetExpression caseBody = new TargetMethodCall(
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TargetExpression generatePatternOverloadsRec(int offset, TargetExpression switchExpr, List<TargetLocalVar> params, List<TargetPattern> patterns, List<TargetMethod> methods, TargetType classType) {
|
||||||
|
if (methods.isEmpty()) throw new DebugException("Couldn't find a candidate for switch overloading");
|
||||||
|
if (methods.size() == 1) {
|
||||||
|
var method = methods.getFirst();
|
||||||
|
var mParams = new ArrayList<TargetExpression>();
|
||||||
|
for (var i = 0; i < params.size(); i++) {
|
||||||
|
var tpe = method.signature().parameters().get(i).pattern().type();
|
||||||
|
mParams.add(new TargetLocalVar(tpe, params.get(i).name()));
|
||||||
|
}
|
||||||
|
TargetExpression caseBody = new TargetMethodCall(
|
||||||
method.signature().returnType(),
|
method.signature().returnType(),
|
||||||
new TargetThis(classType),
|
new TargetThis(classType),
|
||||||
mParams,
|
mParams,
|
||||||
classType,
|
classType,
|
||||||
method.name(),
|
method.name(),
|
||||||
false, false, method.isPrivate()
|
false, false, method.isPrivate()
|
||||||
);
|
);
|
||||||
if (method.signature().returnType() != null) {
|
if (method.signature().returnType() != null) {
|
||||||
caseBody = new TargetReturn(caseBody);
|
caseBody = new TargetReturn(caseBody);
|
||||||
}
|
}
|
||||||
return caseBody;
|
return caseBody;
|
||||||
}
|
|
||||||
|
|
||||||
private static TargetExpression generatePatternOverloadsRec(int offset, TargetExpression switchExpr, List<TargetLocalVar> params, List<TargetPattern> patterns, List<TargetMethod> methods, TargetType classType) {
|
|
||||||
if (methods.isEmpty()) throw new DebugException("Couldn't find a candidate for switch overloading");
|
|
||||||
if (methods.size() == 1) {
|
|
||||||
var method = methods.getFirst();
|
|
||||||
return generateCall(method, params, classType);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var cases = new ArrayList<TargetSwitch.Case>();
|
var cases = new ArrayList<TargetSwitch.Case>();
|
||||||
@@ -561,157 +542,53 @@ public class ASTToTargetAST {
|
|||||||
if (!patternsRec.get(j).equals(param.pattern())) return false;
|
if (!patternsRec.get(j).equals(param.pattern())) return false;
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
return false;
|
return true;
|
||||||
}).toList();
|
}).toList();
|
||||||
|
|
||||||
if (candidates.isEmpty()) {
|
//System.out.println(offset + " -> " + lastPattern);
|
||||||
var body = new TargetBlock(List.of(generateCall(method, params, classType)));
|
//candidates.forEach(m -> System.out.println(m.getSignature()));
|
||||||
cases.add(new TargetSwitch.Case(List.of(lastPattern), body));
|
var caseBody = generatePatternOverloadsRec(offset + 1, expr, params, patternsRec, candidates, classType);
|
||||||
} else {
|
var body = new TargetBlock(List.of(caseBody));
|
||||||
//candidates.forEach(m -> System.out.println(m.getSignature()));
|
var case_ = new TargetSwitch.Case(List.of(lastPattern), body);
|
||||||
var caseBody = generatePatternOverloadsRec(offset + 1, expr, params, patternsRec, candidates, classType);
|
|
||||||
var body = new TargetBlock(List.of(caseBody));
|
|
||||||
var case_ = new TargetSwitch.Case(List.of(lastPattern), body);
|
|
||||||
|
|
||||||
cases.add(case_);
|
cases.add(case_);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new TargetSwitch(switchExpr, cases, null, true);
|
return new TargetSwitch(switchExpr, cases, null, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<TargetType> transferParameters(ClassOrInterface type, ClassOrInterface intf, List<TargetType> params) {
|
private List<TargetMethod> generatePatternOverloads(ClassOrInterface clazz, List<MethodWithTphs> overloadedMethods) {
|
||||||
if (params.isEmpty()) return List.of();
|
|
||||||
var map = new HashMap<String, TargetType>();
|
|
||||||
var generics = Lists.newArrayList(type.getGenerics());
|
|
||||||
for (var i = 0; i < params.size(); i++) {
|
|
||||||
var name = generics.get(i).getName();
|
|
||||||
var gtype = params.get(i);
|
|
||||||
map.put(name, gtype);
|
|
||||||
}
|
|
||||||
var intfGenerics = Lists.newArrayList(intf.getGenerics());
|
|
||||||
var insertedGenerics = new TargetType[intfGenerics.size()];
|
|
||||||
for (var i = 0; i < intfGenerics.size(); i++) {
|
|
||||||
insertedGenerics[i] = map.get(intfGenerics.get(i).getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
return Lists.newArrayList(insertedGenerics);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO What happens if a record implements two sealed interfaces?
|
|
||||||
private Optional<TargetType> commonSealedInterface(TargetType a, TargetType b) {
|
|
||||||
if (!(a instanceof TargetRefType ar && b instanceof TargetRefType br)) return Optional.empty();
|
|
||||||
var cla = compiler.getClass(new JavaClassName(ar.name()));
|
|
||||||
var clb = compiler.getClass(new JavaClassName(br.name()));
|
|
||||||
|
|
||||||
// TODO This only goes one layer deep, this is fine for records as they can't extend anything but fails for complex hierarchies
|
|
||||||
var intersection = new HashSet<>(cla.getSuperInterfaces());
|
|
||||||
intersection.retainAll(clb.getSuperInterfaces());
|
|
||||||
|
|
||||||
var intfclass = compiler.getClass(intersection.iterator().next().getName());
|
|
||||||
// We need to map the generics
|
|
||||||
var insertedParamsA = transferParameters(cla, intfclass, ar.params());
|
|
||||||
var insertedParamsB = transferParameters(clb, intfclass, br.params());
|
|
||||||
// Make sure both insertions yield the same parameters
|
|
||||||
if (!typesStrictlyEqual(insertedParamsA, insertedParamsB)) return Optional.empty();
|
|
||||||
|
|
||||||
if (intersection.size() != 1) return Optional.empty();
|
|
||||||
return Optional.of(new TargetRefType(intfclass.getClassName().toString(), insertedParamsA));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Optional<TargetMethod> generateBridgeMethod(ClassOrInterface clazz, List<TargetMethod> methods) {
|
|
||||||
// If there's only one method we don't need a bridge
|
|
||||||
if (methods.size() <= 1) return Optional.empty();
|
|
||||||
var firstMethod = methods.getFirst();
|
|
||||||
var ra = firstMethod.signature().returnType();
|
|
||||||
|
|
||||||
// Check if all parameters are either the same or implement a sealed interface
|
|
||||||
var resParams = new ArrayList<>(firstMethod.signature().parameters());
|
|
||||||
TargetType resRet = firstMethod.signature().returnType();
|
|
||||||
|
|
||||||
for (var m : methods.subList(1, methods.size())) {
|
|
||||||
for (var i = 0; i < m.signature().parameters().size(); i++) {
|
|
||||||
var pa = firstMethod.signature().parameters().get(i);
|
|
||||||
var pb = m.signature().parameters().get(i);
|
|
||||||
|
|
||||||
var ta = pa.pattern().type();
|
|
||||||
var tb = pb.pattern().type();
|
|
||||||
//System.out.println(ta + " " + tb);
|
|
||||||
|
|
||||||
if (Objects.equals(ta, tb)) continue;
|
|
||||||
var common = commonSealedInterface(ta, tb);
|
|
||||||
if (common.isPresent()) {
|
|
||||||
resParams.set(i, pa.withType(common.get()));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
var rb = m.signature().returnType();
|
|
||||||
|
|
||||||
if (Objects.equals(ra, rb)) continue;
|
|
||||||
var common = commonSealedInterface(ra, rb);
|
|
||||||
if (common.isPresent()) resRet = common.get();
|
|
||||||
else return Optional.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
var parameters = resParams.stream().map( p -> new TargetLocalVar(p.pattern().type(), p.pattern().name())).toList();
|
|
||||||
|
|
||||||
var classType = new TargetRefType(clazz.getClassName().getClassName());
|
|
||||||
var stmt = generatePatternOverloadsRec(0, new TargetLocalVar(resParams.getFirst().pattern().type(), resParams.getFirst().pattern().name()), parameters, List.of(), methods, classType);
|
|
||||||
var block = new TargetBlock(List.of(stmt));
|
|
||||||
|
|
||||||
var generics = new HashSet<>(firstMethod.signature().generics());
|
|
||||||
var resSig = new TargetMethod.Signature(generics, resParams, resRet);
|
|
||||||
correctGenerics(resSig, generics.stream().toList());
|
|
||||||
var bridgeMethod = new TargetMethod(firstMethod.access(), firstMethod.name(), block, resSig, resSig);
|
|
||||||
return Optional.of(bridgeMethod);
|
|
||||||
}
|
|
||||||
|
|
||||||
private int comparePattern(TargetPattern a, TargetPattern b) {
|
|
||||||
if (a instanceof TargetComplexPattern cpa
|
|
||||||
&& b instanceof TargetComplexPattern cpb
|
|
||||||
&& Objects.equals(cpa.type(), cpb.type())) {
|
|
||||||
|
|
||||||
assert cpa.subPatterns().size() == cpb.subPatterns().size();
|
|
||||||
for (var i = 0; i < cpa.subPatterns().size(); i++) {
|
|
||||||
var c = comparePattern(cpa.subPatterns().get(i), cpb.subPatterns().get(i));
|
|
||||||
if (c != 0) return c;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isSubtype(a.type(), b.type())) return -1;
|
|
||||||
if (isSubtype(b.type(), a.type())) return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private class CompareBySpecificity implements Comparator<MethodWithTphs> {
|
|
||||||
@Override
|
|
||||||
public int compare(MethodWithTphs o1, MethodWithTphs o2) {
|
|
||||||
var p1 = o1.signature.java.parameters();
|
|
||||||
var p2 = o2.signature.java.parameters();
|
|
||||||
if (p1.size() != p2.size()) return 0;
|
|
||||||
for (var i = 0; i < p1.size(); i++) {
|
|
||||||
var c = comparePattern(p1.get(i).pattern(), p2.get(i).pattern());
|
|
||||||
if (c != 0) return c;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sortBySpecificity(List<MethodWithTphs> methods) {
|
|
||||||
methods.sort(new CompareBySpecificity());
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<TargetMethod> generatePatternOverloads(ClassOrInterface clazz, MethodGroup group) {
|
|
||||||
var overloadedMethods = new ArrayList<>(group.methods);
|
|
||||||
if (overloadedMethods.isEmpty()) return List.of();
|
if (overloadedMethods.isEmpty()) return List.of();
|
||||||
// Check if we have a pattern as a parameter
|
// Check if we have a pattern as a parameter
|
||||||
sortBySpecificity(overloadedMethods);
|
var firstMethod = convert(overloadedMethods.getFirst(), overloadedMethods.getFirst().generics.javaGenerics);
|
||||||
var firstMethod = convert(overloadedMethods.getFirst());
|
|
||||||
if (overloadedMethods.size() == 1) return List.of(firstMethod);
|
if (overloadedMethods.size() == 1) return List.of(firstMethod);
|
||||||
var signatureParams = group.signature.java.parameters();
|
var secondMethod = convert(overloadedMethods.get(1), overloadedMethods.get(1).generics.javaGenerics);
|
||||||
|
if (firstMethod.signature().parameters().stream().noneMatch(mp -> mp.pattern() instanceof TargetComplexPattern))
|
||||||
|
return overloadedMethods.stream().map(m -> convert(m, m.generics.javaGenerics)).toList();
|
||||||
|
|
||||||
|
var signatureParams = new ArrayList<MethodParameter>();
|
||||||
|
for (var i = 0; i < firstMethod.signature().parameters().size(); i++) {
|
||||||
|
var p1 = firstMethod.signature().parameters().get(i).pattern();
|
||||||
|
var t1 = p1.type();
|
||||||
|
var t2 = secondMethod.signature().parameters().get(i).pattern().type();
|
||||||
|
var commonSubTypes = new HashSet<>(commonSuperInterfaceTypes(t1, t2));
|
||||||
|
for (var m : overloadedMethods.subList(2, overloadedMethods.size())) {
|
||||||
|
var t3 = m.signature().java.parameters().get(i).pattern().type();
|
||||||
|
commonSubTypes.retainAll(commonSuperInterfaceTypes(t1, t3));
|
||||||
|
}
|
||||||
|
if (commonSubTypes.size() > 1) throw new DebugException("Invalid overload");
|
||||||
|
// TODO accept multiple types
|
||||||
|
var superType = ASTFactory.createObjectClass();
|
||||||
|
if (!commonSubTypes.isEmpty())
|
||||||
|
superType = commonSubTypes.iterator().next();
|
||||||
|
|
||||||
|
String name;
|
||||||
|
if (p1 instanceof TargetComplexPattern) name = "__var" + i;
|
||||||
|
else name = p1.name();
|
||||||
|
signatureParams.add(new MethodParameter(new TargetRefType(superType.getClassName().toString()), name));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rename existing methods
|
||||||
|
|
||||||
var res = new ArrayList<TargetMethod>();
|
var res = new ArrayList<TargetMethod>();
|
||||||
for (var method : overloadedMethods) {
|
for (var method : overloadedMethods) {
|
||||||
@@ -730,6 +607,12 @@ public class ASTToTargetAST {
|
|||||||
res.add(new TargetMethod(tMethod.access(), name, tMethod.block(), tMethod.signature(), tMethod.txSignature()));
|
res.add(new TargetMethod(tMethod.access(), name, tMethod.block(), tMethod.signature(), tMethod.txSignature()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var commonSubTypes = new HashSet<>(commonSuperInterfaceTypes(firstMethod.signature().returnType(), secondMethod.signature().returnType()));
|
||||||
|
for (var m : overloadedMethods.subList(2, overloadedMethods.size())) {
|
||||||
|
commonSubTypes.retainAll(commonSuperInterfaceTypes(firstMethod.signature().returnType(), m.signature().java.returnType()));
|
||||||
|
}
|
||||||
|
var returnType = commonSubTypes.isEmpty() ? TargetType.Object : new TargetRefType(commonSubTypes.iterator().next().getClassName().toString());
|
||||||
|
|
||||||
var parameters = signatureParams.stream().map( p -> new TargetLocalVar(p.pattern().type(), p.pattern().name())).toList();
|
var parameters = signatureParams.stream().map( p -> new TargetLocalVar(p.pattern().type(), p.pattern().name())).toList();
|
||||||
//var patterns = List.of((TargetComplexPattern) firstMethod.signature().parameters().stream()
|
//var patterns = List.of((TargetComplexPattern) firstMethod.signature().parameters().stream()
|
||||||
// .filter(p -> p.pattern() instanceof TargetComplexPattern).findFirst().orElseThrow().pattern());
|
// .filter(p -> p.pattern() instanceof TargetComplexPattern).findFirst().orElseThrow().pattern());
|
||||||
@@ -739,11 +622,34 @@ public class ASTToTargetAST {
|
|||||||
var stmt = generatePatternOverloadsRec(0, new TargetLocalVar(signatureParams.getFirst().pattern().type(), signatureParams.getFirst().pattern().name()), parameters, List.of(), res, classType);
|
var stmt = generatePatternOverloadsRec(0, new TargetLocalVar(signatureParams.getFirst().pattern().type(), signatureParams.getFirst().pattern().name()), parameters, List.of(), res, classType);
|
||||||
var block = new TargetBlock(List.of(stmt));
|
var block = new TargetBlock(List.of(stmt));
|
||||||
|
|
||||||
var bridgeMethod = new TargetMethod(firstMethod.access(), firstMethod.name(), block, group.signature.java, group.signature.tx);
|
var signature = new TargetMethod.Signature(Set.of(), signatureParams, returnType);
|
||||||
|
var bridgeMethod = new TargetMethod(firstMethod.access(), firstMethod.name(), block, signature, firstMethod.txSignature());
|
||||||
|
|
||||||
res.add(bridgeMethod);
|
res.add(bridgeMethod);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Expression makeRecordSwitch(RefTypeOrTPHOrWildcardOrGeneric returnType, ParameterList params, List<Method> overloadedMethods) {
|
||||||
|
var param = params.getFormalparalist().getFirst();
|
||||||
|
assert param instanceof RecordPattern; // TODO
|
||||||
|
|
||||||
|
var cases = new ArrayList<SwitchBlock>();
|
||||||
|
for (var method : overloadedMethods) {
|
||||||
|
var statements = new ArrayList<Statement>();
|
||||||
|
/*statements.add(new MethodCall(
|
||||||
|
method.getReturnType(), new ExpressionReceiver(new This(new NullToken())), method.name,
|
||||||
|
params,
|
||||||
|
));*/
|
||||||
|
|
||||||
|
var block = new Block(statements, new NullToken());
|
||||||
|
var labels = new ArrayList<SwitchLabel>();
|
||||||
|
cases.add(new SwitchBlock(labels, block, true, new NullToken()));
|
||||||
|
}
|
||||||
|
var swtch = new Switch(new LocalVar("par0", param.getType(), new NullToken()), cases, returnType, false, new NullToken());
|
||||||
|
|
||||||
|
return swtch;
|
||||||
|
}
|
||||||
|
|
||||||
private Optional<Method> findSuperMethodToOverride(ClassOrInterface currentClass, String name, List<MethodParameter> params, IGenerics generics) {
|
private Optional<Method> findSuperMethodToOverride(ClassOrInterface currentClass, String name, List<MethodParameter> params, IGenerics generics) {
|
||||||
var superClass = compiler.getClass(currentClass.getSuperClass().getName());
|
var superClass = compiler.getClass(currentClass.getSuperClass().getName());
|
||||||
var methodStream = superClass.getMethods().stream();
|
var methodStream = superClass.getMethods().stream();
|
||||||
@@ -764,15 +670,6 @@ public class ASTToTargetAST {
|
|||||||
}).findFirst();
|
}).findFirst();
|
||||||
}
|
}
|
||||||
|
|
||||||
record MethodGroup(Signature signature, Set<MethodWithTphs> methods) {
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
assert !methods.isEmpty();
|
|
||||||
var first = methods.iterator().next();
|
|
||||||
return signature.java.returnType() + " " + first.method.name + " " + signature.java.generics() + " " + signature.java.parameters();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
record MethodWithTphs(Method method, Generics generics, Signature signature) {
|
record MethodWithTphs(Method method, Generics generics, Signature signature) {
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
@@ -787,31 +684,14 @@ public class ASTToTargetAST {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private TargetMethod convert(MethodWithTphs mtph) {
|
|
||||||
return convert(mtph, mtph.generics.javaGenerics);
|
|
||||||
}
|
|
||||||
|
|
||||||
private TargetMethod convert(MethodWithTphs mtph, IGenerics generics) {
|
private TargetMethod convert(MethodWithTphs mtph, IGenerics generics) {
|
||||||
return new TargetMethod(mtph.method.modifier, mtph.method.name, convert(mtph.method.block, generics), mtph.signature.java(), mtph.signature.tx());
|
return new TargetMethod(mtph.method.modifier, mtph.method.name, convert(mtph.method.block, generics), mtph.signature.java(), mtph.signature.tx());
|
||||||
}
|
}
|
||||||
|
|
||||||
record Signature(TargetMethod.Signature java, TargetMethod.Signature tx, Generics generics) {
|
record Signature(TargetMethod.Signature java, TargetMethod.Signature tx, Generics generics) {}
|
||||||
@Override
|
|
||||||
public boolean equals(Object other) {
|
|
||||||
if (this == other) return true;
|
|
||||||
if (!(other instanceof Signature that)) return false;
|
|
||||||
return Objects.equals(this.java, that.java) && Objects.equals(this.tx, that.tx)
|
|
||||||
&& typesStrictlyEqual(this.java.returnType(), that.java.returnType()) && typesStrictlyEqual(this.tx.returnType(), that.tx.returnType());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
private List<MethodWithTphs> convert(ClassOrInterface currentClass, Method method) {
|
||||||
public int hashCode() {
|
List<MethodWithTphs> result = new ArrayList<>();
|
||||||
return Objects.hash(java, tx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Set<MethodWithTphs> convert(ClassOrInterface currentClass, Method method) {
|
|
||||||
Set<MethodWithTphs> result = new HashSet<>();
|
|
||||||
this.currentMethod = method;
|
this.currentMethod = method;
|
||||||
|
|
||||||
List<Signature> signatures = new ArrayList<>();
|
List<Signature> signatures = new ArrayList<>();
|
||||||
@@ -836,7 +716,7 @@ public class ASTToTargetAST {
|
|||||||
var txMethodGenerics = collectMethodGenerics(currentClass, generics.txGenerics(), txGenerics, method);
|
var txMethodGenerics = collectMethodGenerics(currentClass, generics.txGenerics(), txGenerics, method);
|
||||||
|
|
||||||
var javaSignature = new TargetMethod.Signature(javaMethodGenerics, params, returnType);
|
var javaSignature = new TargetMethod.Signature(javaMethodGenerics, params, returnType);
|
||||||
//System.out.println(javaSignature.getDescriptor());
|
System.out.println(javaSignature.getDescriptor());
|
||||||
var txSignature = new TargetMethod.Signature(txMethodGenerics, txParams, convert(method.getReturnType(), generics.txGenerics, compiler));
|
var txSignature = new TargetMethod.Signature(txMethodGenerics, txParams, convert(method.getReturnType(), generics.txGenerics, compiler));
|
||||||
|
|
||||||
signatures.add(new Signature(javaSignature, txSignature, generics));
|
signatures.add(new Signature(javaSignature, txSignature, generics));
|
||||||
|
|||||||
@@ -3,9 +3,4 @@ package de.dhbwstuttgart.target.tree;
|
|||||||
import de.dhbwstuttgart.target.tree.type.TargetType;
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
|
||||||
public record TargetGeneric(String name, TargetType bound) {
|
public record TargetGeneric(String name, TargetType bound) {
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
if (bound.equals(TargetType.Object)) return "'" + name;
|
|
||||||
else return "'" + name + " < " + bound;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
package de.dhbwstuttgart.target.tree;
|
package de.dhbwstuttgart.target.tree;
|
||||||
|
|
||||||
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||||
import de.dhbwstuttgart.target.tree.type.TargetRefType;
|
|
||||||
import de.dhbwstuttgart.target.tree.type.TargetType;
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public record TargetInterface(int modifiers, JavaClassName qualifiedName, Set<TargetGeneric> generics, Set<TargetGeneric> txGenerics, List<TargetMethod> methods, List<TargetType> implementingInterfaces, TargetMethod staticConstructor, List<TargetRefType> permittedSubtypes) implements TargetStructure {
|
public record TargetInterface(int modifiers, JavaClassName qualifiedName, Set<TargetGeneric> generics, Set<TargetGeneric> txGenerics, List<TargetMethod> methods, List<TargetType> implementingInterfaces, TargetMethod staticConstructor) implements TargetStructure {
|
||||||
@Override
|
@Override
|
||||||
public TargetType superType() {
|
public TargetType superType() {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -736,12 +736,12 @@ public class TYPEStmt implements StatementVisitor {
|
|||||||
|
|
||||||
for (int i = 0; i < foMethod.arglist.getArguments().size(); i++) {
|
for (int i = 0; i < foMethod.arglist.getArguments().size(); i++) {
|
||||||
// Zuordnung von MethoCall.signature (Argumenttypen) zu der Argumenttypen der ausgewaehlten Methode (assumption.params)
|
// Zuordnung von MethoCall.signature (Argumenttypen) zu der Argumenttypen der ausgewaehlten Methode (assumption.params)
|
||||||
ret.add(new Pair(foMethod.signature.get(i), assumption.getArgTypes().get(i), PairOperator.EQUALSDOT));
|
ret.add(new Pair(resolver.resolve(foMethod.signature.get(i)), resolver.resolve(assumption.getArgTypes().get(i)), PairOperator.EQUALSDOT));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Zuordnung von MethodCall.signature(ReturnType) zu dem ReturnType der ausgewaehlten Methode (assumption.returnType)
|
// Zuordnung von MethodCall.signature(ReturnType) zu dem ReturnType der ausgewaehlten Methode (assumption.returnType)
|
||||||
ret.add(new Pair(foMethod.signature.getLast(), assumption.getReturnType(), PairOperator.EQUALSDOT));
|
ret.add(new Pair(resolver.resolve(foMethod.signature.getLast()), resolver.resolve(assumption.getReturnType()), PairOperator.EQUALSDOT));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -755,7 +755,7 @@ public class RuleSet implements IRuleSet{
|
|||||||
|
|
||||||
UnifyType lhsType = pair.getLhsType();
|
UnifyType lhsType = pair.getLhsType();
|
||||||
UnifyType rhsType = pair.getRhsType();
|
UnifyType rhsType = pair.getRhsType();
|
||||||
if(!(lhsType instanceof ReferenceType) || !(rhsType instanceof ExtendsType))
|
if((!(lhsType instanceof ReferenceType) && !(lhsType instanceof FunNType)) || !(rhsType instanceof ExtendsType))
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
|
|
||||||
return Optional.of(new UnifyPair(lhsType, ((ExtendsType) rhsType).getExtendedType(), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair()));
|
return Optional.of(new UnifyPair(lhsType, ((ExtendsType) rhsType).getExtendedType(), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair()));
|
||||||
@@ -781,7 +781,7 @@ public class RuleSet implements IRuleSet{
|
|||||||
|
|
||||||
UnifyType lhsType = pair.getLhsType();
|
UnifyType lhsType = pair.getLhsType();
|
||||||
UnifyType rhsType = pair.getRhsType();
|
UnifyType rhsType = pair.getRhsType();
|
||||||
if(!(lhsType instanceof ReferenceType) || !(rhsType instanceof SuperType))
|
if((!(lhsType instanceof ReferenceType) && !(lhsType instanceof FunNType)) || !(rhsType instanceof SuperType))
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
|
|
||||||
return Optional.of(new UnifyPair(((SuperType) rhsType).getSuperedType(), lhsType, PairOperator.SMALLERDOTWC, pair.getSubstitution(), pair.getBasePair()));
|
return Optional.of(new UnifyPair(((SuperType) rhsType).getSuperedType(), lhsType, PairOperator.SMALLERDOTWC, pair.getSubstitution(), pair.getBasePair()));
|
||||||
@@ -904,7 +904,7 @@ public class RuleSet implements IRuleSet{
|
|||||||
|
|
||||||
var fiArgs = intf.getFunctionalInterfaceTypeArguments(refType);
|
var fiArgs = intf.getFunctionalInterfaceTypeArguments(refType);
|
||||||
var retType = fiArgs.getFirst();
|
var retType = fiArgs.getFirst();
|
||||||
var lhsArgs = intf.getFunctionalInterfaceTypeArguments(lhsType);
|
var lhsArgs = intf.getFunctionalInterfaceTypeArguments(lhsType); //FALSCHRUM????
|
||||||
var lhsRet = lhsArgs.getFirst();
|
var lhsRet = lhsArgs.getFirst();
|
||||||
|
|
||||||
Set<UnifyPair> result = new HashSet<>();
|
Set<UnifyPair> result = new HashSet<>();
|
||||||
@@ -972,15 +972,65 @@ public class RuleSet implements IRuleSet{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<Set<UnifyPair>> smallerFunN(UnifyPair pair) {
|
public Optional<Set<UnifyPair>> smallerFunN(UnifyPair pair, IFiniteClosure fc) {
|
||||||
if(pair.getPairOp() != PairOperator.SMALLERDOT)
|
if(pair.getPairOp() != PairOperator.SMALLERDOT)
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
|
|
||||||
UnifyType lhsType = pair.getLhsType();
|
UnifyType lhsType = pair.getLhsType();
|
||||||
UnifyType rhsType = pair.getRhsType();
|
UnifyType rhsType = pair.getRhsType();
|
||||||
|
|
||||||
if(!(lhsType instanceof PlaceholderType) || !(rhsType instanceof FunNType))
|
if(!(rhsType instanceof FunNType))
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
|
|
||||||
|
/* muss nach angepasst werden */
|
||||||
|
//FunN$$<...> <. FunctinalInterface<...> wird umgewandelt in FunN$$<...> <. FunN$$<... args aus FuntionalInterface ...>
|
||||||
|
if (lhsType instanceof ReferenceType) {
|
||||||
|
UnifyType typeFI = pair.getLhsType();
|
||||||
|
|
||||||
|
Optional<UnifyType> opt = fc.getRightHandedFunctionalInterfaceType(typeFI.getName());
|
||||||
|
if(!opt.isPresent())
|
||||||
|
return Optional.empty();
|
||||||
|
|
||||||
|
if (!(typeFI instanceof ReferenceType refType) || !(refType instanceof FunInterfaceType intf))
|
||||||
|
return Optional.empty();
|
||||||
|
|
||||||
|
var fiArgs = intf.getFunctionalInterfaceTypeArguments(refType);
|
||||||
|
var retType = fiArgs.getFirst();
|
||||||
|
var rhsArgs = intf.getFunctionalInterfaceTypeArguments(rhsType);
|
||||||
|
var rhsRet = rhsArgs.getFirst();
|
||||||
|
|
||||||
|
Set<UnifyPair> result = new HashSet<>();
|
||||||
|
//if (retType instanceof ExtendsType) {
|
||||||
|
result.add(new UnifyPair(retType, rhsRet, PairOperator.SMALLER));
|
||||||
|
//} else if (retType instanceof SuperType) {
|
||||||
|
// return Optional.empty();
|
||||||
|
//} else {
|
||||||
|
// result.add(new UnifyPair(lhsRet, retType, PairOperator.EQUALSDOT));
|
||||||
|
//}
|
||||||
|
|
||||||
|
for (var i = 1; i < fiArgs.size(); i++) {
|
||||||
|
var rh = rhsArgs.get(i);
|
||||||
|
var lh = fiArgs.get(i);
|
||||||
|
|
||||||
|
//if (rh instanceof SuperType) {
|
||||||
|
result.add(new UnifyPair(rh, lh, PairOperator.SMALLER));
|
||||||
|
//} else if (rh instanceof ExtendsType) {
|
||||||
|
// return Optional.empty();
|
||||||
|
//} else {
|
||||||
|
// result.add(new UnifyPair(lh, rh, PairOperator.EQUALSDOT));
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Optional.of(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
if(!(lhsType instanceof PlaceholderType))
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
FunNType funNRhsType = (FunNType) rhsType;
|
FunNType funNRhsType = (FunNType) rhsType;
|
||||||
|
|
||||||
@@ -1017,7 +1067,122 @@ public class RuleSet implements IRuleSet{
|
|||||||
|
|
||||||
return Optional.of(result);
|
return Optional.of(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Set<UnifyPair>> reduceFIFunN(UnifyPair pair, IFiniteClosure fc) {
|
||||||
|
if(pair.getPairOp() != PairOperator.EQUALSDOT)
|
||||||
|
return Optional.empty();
|
||||||
|
|
||||||
|
UnifyType lhsType = pair.getLhsType();
|
||||||
|
UnifyType rhsType = pair.getRhsType();
|
||||||
|
|
||||||
|
if(!(rhsType instanceof FunNType))
|
||||||
|
return Optional.empty();
|
||||||
|
|
||||||
|
/* muss nach angepasst werden */
|
||||||
|
//FunN$$<...> <. FunctinalInterface<...> wird umgewandelt in FunN$$<...> <. FunN$$<... args aus FuntionalInterface ...>
|
||||||
|
if (lhsType instanceof ReferenceType) {
|
||||||
|
UnifyType typeFI = pair.getLhsType();
|
||||||
|
|
||||||
|
Optional<UnifyType> opt = fc.getRightHandedFunctionalInterfaceType(typeFI.getName());
|
||||||
|
if(!opt.isPresent())
|
||||||
|
return Optional.empty();
|
||||||
|
|
||||||
|
if (!(typeFI instanceof ReferenceType refType) || !(refType instanceof FunInterfaceType intf))
|
||||||
|
return Optional.empty();
|
||||||
|
|
||||||
|
var fiArgs = intf.getFunctionalInterfaceTypeArguments(refType);
|
||||||
|
var retType = fiArgs.getFirst();
|
||||||
|
var rhsArgs = intf.getFunctionalInterfaceTypeArguments(rhsType);
|
||||||
|
var rhsRet = rhsArgs.getFirst();
|
||||||
|
|
||||||
|
Set<UnifyPair> result = new HashSet<>();
|
||||||
|
//if (retType instanceof ExtendsType) {
|
||||||
|
result.add(new UnifyPair(retType, rhsRet, PairOperator.EQUALSDOT));
|
||||||
|
//} else if (retType instanceof SuperType) {
|
||||||
|
// return Optional.empty();
|
||||||
|
//} else {
|
||||||
|
// result.add(new UnifyPair(lhsRet, retType, PairOperator.EQUALSDOT));
|
||||||
|
//}
|
||||||
|
|
||||||
|
for (var i = 1; i < fiArgs.size(); i++) {
|
||||||
|
var rh = rhsArgs.get(i);
|
||||||
|
var lh = fiArgs.get(i);
|
||||||
|
|
||||||
|
//if (rh instanceof SuperType) {
|
||||||
|
result.add(new UnifyPair(rh, lh, PairOperator.EQUALSDOT));
|
||||||
|
//} else if (rh instanceof ExtendsType) {
|
||||||
|
// return Optional.empty();
|
||||||
|
//} else {
|
||||||
|
// result.add(new UnifyPair(lh, rh, PairOperator.EQUALSDOT));
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Optional.of(result);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Set<UnifyPair>> reduceFunNFi(UnifyPair pair, IFiniteClosure fc) {
|
||||||
|
if(pair.getPairOp() != PairOperator.EQUALSDOT)
|
||||||
|
return Optional.empty();
|
||||||
|
|
||||||
|
UnifyType lhsType = pair.getLhsType();
|
||||||
|
UnifyType rhsType = pair.getRhsType();
|
||||||
|
|
||||||
|
if(!(lhsType instanceof FunNType))
|
||||||
|
return Optional.empty();
|
||||||
|
|
||||||
|
//FunN$$<...> <. FunctinalInterface<...> wird umgewandelt in FunN$$<...> <. FunN$$<... args aus FuntionalInterface ...>
|
||||||
|
if (rhsType instanceof ReferenceType) {
|
||||||
|
UnifyType typeFI = pair.getRhsType();
|
||||||
|
|
||||||
|
Optional<UnifyType> opt = fc.getRightHandedFunctionalInterfaceType(typeFI.getName());
|
||||||
|
if(!opt.isPresent())
|
||||||
|
return Optional.empty();
|
||||||
|
|
||||||
|
if (!(typeFI instanceof ReferenceType refType) || !(refType instanceof FunInterfaceType intf))
|
||||||
|
return Optional.empty();
|
||||||
|
|
||||||
|
var fiArgs = intf.getFunctionalInterfaceTypeArguments(refType);
|
||||||
|
var retType = fiArgs.getFirst();
|
||||||
|
var lhsArgs = intf.getFunctionalInterfaceTypeArguments(lhsType);
|
||||||
|
var lhsRet = lhsArgs.getFirst();
|
||||||
|
|
||||||
|
Set<UnifyPair> result = new HashSet<>();
|
||||||
|
//if (retType instanceof ExtendsType) {
|
||||||
|
// result.add(new UnifyPair(lhsRet, retType, PairOperator.SMALLERDOTWC));
|
||||||
|
//} else if (retType instanceof SuperType) {
|
||||||
|
// return Optional.empty();
|
||||||
|
//} else {
|
||||||
|
result.add(new UnifyPair(lhsRet, retType, PairOperator.EQUALSDOT));
|
||||||
|
//}
|
||||||
|
|
||||||
|
for (var i = 1; i < fiArgs.size(); i++) {
|
||||||
|
var lh = lhsArgs.get(i);
|
||||||
|
var rh = fiArgs.get(i);
|
||||||
|
|
||||||
|
//if (rh instanceof SuperType) {
|
||||||
|
// result.add(new UnifyPair(lh, rh, PairOperator.SMALLERDOTWC));
|
||||||
|
//} else if (rh instanceof ExtendsType) {
|
||||||
|
// return Optional.empty();
|
||||||
|
//} else {
|
||||||
|
result.add(new UnifyPair(lh, rh, PairOperator.EQUALSDOT));
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Optional.of(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<UnifyPair> reduceTph(UnifyPair pair) {
|
public Optional<UnifyPair> reduceTph(UnifyPair pair) {
|
||||||
if(pair.getPairOp() != PairOperator.SMALLERDOTWC)
|
if(pair.getPairOp() != PairOperator.SMALLERDOTWC)
|
||||||
@@ -1025,7 +1190,7 @@ public class RuleSet implements IRuleSet{
|
|||||||
|
|
||||||
UnifyType lhsType = pair.getLhsType();
|
UnifyType lhsType = pair.getLhsType();
|
||||||
UnifyType rhsType = pair.getRhsType();
|
UnifyType rhsType = pair.getRhsType();
|
||||||
if(!(lhsType instanceof PlaceholderType) || !(rhsType instanceof ReferenceType))
|
if(!(lhsType instanceof PlaceholderType) || (!(rhsType instanceof ReferenceType) && !(rhsType instanceof FunNType)))
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
|
|
||||||
return Optional.of(new UnifyPair(lhsType, rhsType, PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair()));
|
return Optional.of(new UnifyPair(lhsType, rhsType, PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair()));
|
||||||
|
|||||||
@@ -1239,7 +1239,7 @@ public class TypeUnifyTask extends CancellableTask<CompletableFuture<Set<Set<Uni
|
|||||||
// FunN Rules
|
// FunN Rules
|
||||||
optSet = optSet.isPresent() ? optSet : rules.reduceFunN(pair);
|
optSet = optSet.isPresent() ? optSet : rules.reduceFunN(pair);
|
||||||
optSet = optSet.isPresent() ? optSet : rules.greaterFunN(pair, fc);
|
optSet = optSet.isPresent() ? optSet : rules.greaterFunN(pair, fc);
|
||||||
optSet = optSet.isPresent() ? optSet : rules.smallerFunN(pair);
|
optSet = optSet.isPresent() ? optSet : rules.smallerFunN(pair, fc);
|
||||||
|
|
||||||
// One of the rules has been applied
|
// One of the rules has been applied
|
||||||
if (optSet.isPresent()) {
|
if (optSet.isPresent()) {
|
||||||
|
|||||||
@@ -39,7 +39,8 @@ public class UnifyResultModel {
|
|||||||
public void notify(Set<Set<UnifyPair>> eqPrimePrimeSet, UnifyContext context) {
|
public void notify(Set<Set<UnifyPair>> eqPrimePrimeSet, UnifyContext context) {
|
||||||
Set<Set<UnifyPair>> eqPrimePrimeSetRet = eqPrimePrimeSet.stream().map(x -> {
|
Set<Set<UnifyPair>> eqPrimePrimeSetRet = eqPrimePrimeSet.stream().map(x -> {
|
||||||
Optional<Set<UnifyPair>> res = new RuleSet(context.placeholderRegistry()).subst(x.stream().map(y -> {
|
Optional<Set<UnifyPair>> res = new RuleSet(context.placeholderRegistry()).subst(x.stream().map(y -> {
|
||||||
if (y.getPairOp() == PairOperator.SMALLERDOTWC) y.setPairOp(PairOperator.EQUALSDOT);
|
if (y.getPairOp() == PairOperator.SMALLERDOTWC)
|
||||||
|
y.setPairOp(PairOperator.EQUALSDOT);
|
||||||
return y; //alle Paare a <.? b erden durch a =. b ersetzt
|
return y; //alle Paare a <.? b erden durch a =. b ersetzt
|
||||||
}).collect(Collectors.toCollection(HashSet::new)));
|
}).collect(Collectors.toCollection(HashSet::new)));
|
||||||
if (res.isPresent()) {//wenn subst ein Erg liefert wurde was veraendert
|
if (res.isPresent()) {//wenn subst ein Erg liefert wurde was veraendert
|
||||||
|
|||||||
@@ -61,7 +61,9 @@ public interface IRuleSet {
|
|||||||
*/
|
*/
|
||||||
public Optional<Set<UnifyPair>> reduceFunN(UnifyPair pair);
|
public Optional<Set<UnifyPair>> reduceFunN(UnifyPair pair);
|
||||||
public Optional<Set<UnifyPair>> greaterFunN(UnifyPair pair, IFiniteClosure fc);
|
public Optional<Set<UnifyPair>> greaterFunN(UnifyPair pair, IFiniteClosure fc);
|
||||||
public Optional<Set<UnifyPair>> smallerFunN(UnifyPair pair);
|
public Optional<Set<UnifyPair>> smallerFunN(UnifyPair pair, IFiniteClosure fc);
|
||||||
|
public Optional<Set<UnifyPair>> reduceFIFunN(UnifyPair pair, IFiniteClosure fc);
|
||||||
|
public Optional<Set<UnifyPair>> reduceFunNFi(UnifyPair pair, IFiniteClosure fc);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether the erase1-Rule applies to the pair.
|
* Checks whether the erase1-Rule applies to the pair.
|
||||||
|
|||||||
@@ -684,6 +684,7 @@ public class FiniteClosure //extends Ordering<UnifyType> //entfernt PL 2018-12-1
|
|||||||
|
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<UnifyType> getAncestors(UnifyType t) {
|
public Set<UnifyType> getAncestors(UnifyType t) {
|
||||||
|
|||||||
@@ -14,7 +14,9 @@ import org.junit.jupiter.api.Test;
|
|||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.core.ConsoleInterface;
|
||||||
import de.dhbwstuttgart.core.JavaTXCompiler;
|
import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||||
|
import de.dhbwstuttgart.util.Logger.LogLevel;
|
||||||
|
|
||||||
public class AllgemeinTest {
|
public class AllgemeinTest {
|
||||||
|
|
||||||
@@ -29,6 +31,7 @@ public class AllgemeinTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test() throws Exception {
|
public void test() throws Exception {
|
||||||
|
ConsoleInterface.logLevel = LogLevel.DEBUG;
|
||||||
//String className = "GenTest";
|
//String className = "GenTest";
|
||||||
//String className = "Overloading_Generics";
|
//String className = "Overloading_Generics";
|
||||||
//String className = "Generics";
|
//String className = "Generics";
|
||||||
@@ -63,11 +66,15 @@ public class AllgemeinTest {
|
|||||||
//String className = "Cycle";
|
//String className = "Cycle";
|
||||||
//String className = "TripleTest";
|
//String className = "TripleTest";
|
||||||
//String className = "WildcardList";
|
//String className = "WildcardList";
|
||||||
String className = "List";
|
//String className = "List";
|
||||||
//String className = "Box";
|
//String className = "Box";
|
||||||
//String className = "GenBox";
|
//String className = "GenBox";
|
||||||
//String className = "InnerInf";
|
//String className = "InnerInf";
|
||||||
//String className = "Foo";
|
//String className = "Foo";
|
||||||
|
|
||||||
|
//String className = "Kombinatoren_failure";
|
||||||
|
String className = "Kombinatoren_After_Lazy";
|
||||||
|
//String className = "Parser";
|
||||||
//PL 2019-10-24: genutzt fuer unterschiedliche Tests
|
//PL 2019-10-24: genutzt fuer unterschiedliche Tests
|
||||||
path = System.getProperty("user.dir")+"/resources/AllgemeinTest/" + className + ".jav";
|
path = System.getProperty("user.dir")+"/resources/AllgemeinTest/" + className + ".jav";
|
||||||
//path = System.getProperty("user.dir")+"/src/test/resources/AllgemeinTest/Overloading_Generics.jav";
|
//path = System.getProperty("user.dir")+"/src/test/resources/AllgemeinTest/Overloading_Generics.jav";
|
||||||
@@ -76,7 +83,7 @@ public class AllgemeinTest {
|
|||||||
///*
|
///*
|
||||||
compiler = new JavaTXCompiler(
|
compiler = new JavaTXCompiler(
|
||||||
Lists.newArrayList(new File(path)),
|
Lists.newArrayList(new File(path)),
|
||||||
Lists.newArrayList(new File(System.getProperty("user.dir")+"/resources/bytecode/classFiles/")),
|
Lists.newArrayList(new File(System.getProperty("user.dir")+"/resources/AllgemeinTest/")),
|
||||||
new File(System.getProperty("user.dir")+"/resources/bytecode/classFiles/"), true);
|
new File(System.getProperty("user.dir")+"/resources/bytecode/classFiles/"), true);
|
||||||
//*/
|
//*/
|
||||||
compiler.generateBytecode();
|
compiler.generateBytecode();
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
|
|
||||||
import de.dhbwstuttgart.core.ConsoleInterface;
|
import de.dhbwstuttgart.core.ConsoleInterface;
|
||||||
import de.dhbwstuttgart.util.Logger;
|
import de.dhbwstuttgart.util.Logger;
|
||||||
|
import de.dhbwstuttgart.util.Logger.LogLevel;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Disabled;
|
import org.junit.jupiter.api.Disabled;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
@@ -953,44 +955,16 @@ public class TestComplete {
|
|||||||
var list1 = ConsCtor.newInstance(1, ConsCtor.newInstance(2, ConsCtor.newInstance(3, EmptyCtor.newInstance())));
|
var list1 = ConsCtor.newInstance(1, ConsCtor.newInstance(2, ConsCtor.newInstance(3, EmptyCtor.newInstance())));
|
||||||
var list2 = ConsCtor.newInstance(4, ConsCtor.newInstance(5, ConsCtor.newInstance(6, EmptyCtor.newInstance())));
|
var list2 = ConsCtor.newInstance(4, ConsCtor.newInstance(5, ConsCtor.newInstance(6, EmptyCtor.newInstance())));
|
||||||
|
|
||||||
var append = clazz.getDeclaredMethod("append", List, List);
|
var append = clazz.getDeclaredMethod("append", Cons, Cons);
|
||||||
System.out.println(append.invoke(instance, list1, list2));
|
System.out.println(append.invoke(instance, list1, list2));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testPatternMatchingSpecificity() throws Exception {
|
|
||||||
var classFiles = generateClassFiles(createClassLoader(), "PatternMatchingSpecificity.jav");
|
|
||||||
|
|
||||||
var clazz = classFiles.get("PatternMatchingSpecificity");
|
|
||||||
var instance = clazz.getDeclaredConstructor().newInstance();
|
|
||||||
var R = classFiles.get("R");
|
|
||||||
|
|
||||||
Integer i = 20;
|
|
||||||
var r = R.getDeclaredConstructor(Number.class).newInstance(i);
|
|
||||||
|
|
||||||
var m = clazz.getDeclaredMethod("m", R);
|
|
||||||
assertEquals(1, m.invoke(instance, r));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPatternMatchingZip() throws Exception {
|
public void testPatternMatchingZip() throws Exception {
|
||||||
//ConsoleInterface.logLevel = Logger.LogLevel.DEBUG;
|
ConsoleInterface.logLevel = LogLevel.DEBUG;
|
||||||
var classFiles = generateClassFiles(createClassLoader(), "PatternMatching.jav");
|
var classFiles = generateClassFiles(createClassLoader(), false,"PatternMatchingJava2.jav", "PatternMatching.jav");
|
||||||
var clazz = classFiles.get("PatternMatching");
|
var clazz = classFiles.get("PatternMatching");
|
||||||
var instance = clazz.getDeclaredConstructor().newInstance();
|
var instance = clazz.getDeclaredConstructor().newInstance();
|
||||||
|
|
||||||
var Cons = classFiles.get("Cons");
|
|
||||||
var Empty = classFiles.get("Empty");
|
|
||||||
var List = classFiles.get("List");
|
|
||||||
|
|
||||||
var ConsCtor = Cons.getDeclaredConstructor(Object.class, List);
|
|
||||||
var EmptyCtor = Empty.getDeclaredConstructor();
|
|
||||||
|
|
||||||
var list1 = ConsCtor.newInstance(1, ConsCtor.newInstance(2, ConsCtor.newInstance(3, EmptyCtor.newInstance())));
|
|
||||||
var list2 = ConsCtor.newInstance(4, ConsCtor.newInstance(5, ConsCtor.newInstance(6, EmptyCtor.newInstance())));
|
|
||||||
|
|
||||||
var zip = clazz.getDeclaredMethod("zip", List, List);
|
|
||||||
System.out.println(zip.invoke(instance, list1, list2));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -1416,6 +1390,7 @@ public class TestComplete {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@Disabled("too slow")
|
||||||
public void testBug325() throws Exception {
|
public void testBug325() throws Exception {
|
||||||
var classFiles = generateClassFiles(createClassLoader(), "Bug325.jav");
|
var classFiles = generateClassFiles(createClassLoader(), "Bug325.jav");
|
||||||
var clazz = classFiles.get("Bug325");
|
var clazz = classFiles.get("Bug325");
|
||||||
@@ -1577,11 +1552,4 @@ public class TestComplete {
|
|||||||
var clazz = classFiles.get("Bug390");
|
var clazz = classFiles.get("Bug390");
|
||||||
clazz.getDeclaredMethod("main", List.class).invoke(null, List.of());
|
clazz.getDeclaredMethod("main", List.class).invoke(null, List.of());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testBug392() throws Exception {
|
|
||||||
var classFiles = generateClassFiles(createClassLoader(), "Bug392.jav");
|
|
||||||
var clazz = classFiles.get("Bug392");
|
|
||||||
clazz.getDeclaredMethod("main", List.class).invoke(null, List.of());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,11 +19,14 @@ public class TestTypeDeployment {
|
|||||||
var path = Path.of(System.getProperty("user.dir"), "/resources/bytecode/javFiles/Cycle.jav");
|
var path = Path.of(System.getProperty("user.dir"), "/resources/bytecode/javFiles/Cycle.jav");
|
||||||
var file = path.toFile();
|
var file = path.toFile();
|
||||||
var compiler = new JavaTXCompiler(file);
|
var compiler = new JavaTXCompiler(file);
|
||||||
compiler.parseAll();
|
|
||||||
var parsedSource = compiler.sourceFiles.get(file);
|
var parsedSource = compiler.sourceFiles.get(file);
|
||||||
var tiResults = compiler.typeInference(file);
|
var tiResults = compiler.typeInference(file);
|
||||||
Set<TypeInsert> tips = new HashSet<>();
|
Set<TypeInsert> tips = new HashSet<>();
|
||||||
|
|
||||||
|
for (var sf : compiler.sourceFiles.values()) {
|
||||||
|
Map<JavaClassName, byte[]> bytecode = compiler.generateBytecode(sf, tiResults);
|
||||||
|
}
|
||||||
|
|
||||||
System.out.println(compiler.getGeneratedGenerics());
|
System.out.println(compiler.getGeneratedGenerics());
|
||||||
|
|
||||||
for (int i = 0; i < tiResults.size(); i++) {
|
for (int i = 0; i < tiResults.size(); i++) {
|
||||||
|
|||||||
@@ -59,7 +59,6 @@ public class ServerTest {
|
|||||||
|
|
||||||
// get information from the compiler
|
// get information from the compiler
|
||||||
JavaTXCompiler compiler = new JavaTXCompiler(List.of(file));
|
JavaTXCompiler compiler = new JavaTXCompiler(List.of(file));
|
||||||
compiler.parseAll();
|
|
||||||
|
|
||||||
// NOW: simulate the call to method typeInference. Once via server and once locally
|
// NOW: simulate the call to method typeInference. Once via server and once locally
|
||||||
// if everything works, they should neither interfere with each other nor differ in their result
|
// if everything works, they should neither interfere with each other nor differ in their result
|
||||||
|
|||||||
@@ -49,7 +49,6 @@ public class TestGenerics {
|
|||||||
private static Result computeGenerics(String filename) throws IOException, ClassNotFoundException {
|
private static Result computeGenerics(String filename) throws IOException, ClassNotFoundException {
|
||||||
var file = Path.of(rootDirectory + filename).toFile();
|
var file = Path.of(rootDirectory + filename).toFile();
|
||||||
var compiler = new JavaTXCompiler(List.of(file), List.of(file.getParentFile()), new File(bytecodeDirectory), true);
|
var compiler = new JavaTXCompiler(List.of(file), List.of(file.getParentFile()), new File(bytecodeDirectory), true);
|
||||||
compiler.parseAll();
|
|
||||||
var inference = compiler.typeInference(file);
|
var inference = compiler.typeInference(file);
|
||||||
compiler.generateBytecode(new File(bytecodeDirectory), inference);
|
compiler.generateBytecode(new File(bytecodeDirectory), inference);
|
||||||
var sf = compiler.sourceFiles.get(file);
|
var sf = compiler.sourceFiles.get(file);
|
||||||
|
|||||||
Reference in New Issue
Block a user