Make the example fail
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 5m47s
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 5m47s
This commit is contained in:
parent
09c483542d
commit
b76e1e46f0
@ -17,6 +17,7 @@ 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 java.lang.annotation.Target;
|
||||||
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;
|
||||||
@ -163,6 +164,7 @@ public class ASTToTargetAST {
|
|||||||
for (var i = 0; i < signature.parameters().size(); i++) {
|
for (var i = 0; i < signature.parameters().size(); i++) {
|
||||||
var p1 = signature.parameters().get(i).pattern().type();
|
var p1 = signature.parameters().get(i).pattern().type();
|
||||||
var p2 = other.signature.parameters().get(i).pattern().type();
|
var p2 = other.signature.parameters().get(i).pattern().type();
|
||||||
|
if (p1 instanceof TargetGenericType && p2 instanceof TargetGenericType) continue;
|
||||||
if (!p1.equals(p2) && commonSuperInterfaceTypes(p1, p2).isEmpty()) return false;
|
if (!p1.equals(p2) && commonSuperInterfaceTypes(p1, p2).isEmpty()) return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -176,6 +178,7 @@ public class ASTToTargetAST {
|
|||||||
|
|
||||||
// This finds a common sealed interface type to group together methods that use different records
|
// This finds a common sealed interface type to group together methods that use different records
|
||||||
private List<ClassOrInterface> commonSuperInterfaceTypes(TargetType a, TargetType b) {
|
private List<ClassOrInterface> commonSuperInterfaceTypes(TargetType a, TargetType b) {
|
||||||
|
if (a instanceof TargetGenericType && b instanceof TargetGenericType) return List.of(ASTFactory.createClass(Object.class));
|
||||||
if (a instanceof TargetRefType ta && b instanceof TargetRefType tb) {
|
if (a instanceof TargetRefType ta && b instanceof TargetRefType tb) {
|
||||||
var res = new HashSet<ClassOrInterface>();
|
var res = new HashSet<ClassOrInterface>();
|
||||||
|
|
||||||
@ -359,14 +362,26 @@ public class ASTToTargetAST {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private TargetExpression generatePatternOverloadsRec(int offset, TargetExpression switchExpr, List<TargetExpression> params, List<TargetComplexPattern> patterns, List<TargetMethod> methods, TargetType classType) {
|
private TargetType unwrap(TargetType type) {
|
||||||
|
if (type instanceof TargetRefType ref) {
|
||||||
|
if (!ref.params().isEmpty()) return new TargetRefType(ref.name());
|
||||||
|
}
|
||||||
|
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.isEmpty()) throw new DebugException("Couldn't find a candidate for switch overloading");
|
||||||
if (methods.size() == 1) {
|
if (methods.size() == 1) {
|
||||||
var method = methods.getFirst();
|
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(
|
TargetExpression caseBody = new TargetMethodCall(
|
||||||
method.signature().returnType(),
|
method.signature().returnType(),
|
||||||
new TargetThis(classType),
|
new TargetThis(classType),
|
||||||
params,
|
mParams,
|
||||||
classType,
|
classType,
|
||||||
method.name(),
|
method.name(),
|
||||||
false, false, method.isPrivate()
|
false, false, method.isPrivate()
|
||||||
@ -378,7 +393,7 @@ public class ASTToTargetAST {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var cases = new ArrayList<TargetSwitch.Case>();
|
var cases = new ArrayList<TargetSwitch.Case>();
|
||||||
var usedPatterns = new HashSet<TargetPattern>();
|
var usedPatterns = new HashSet<TargetType>();
|
||||||
|
|
||||||
for (var method : methods) {
|
for (var method : methods) {
|
||||||
var patternsRec = new ArrayList<>(patterns);
|
var patternsRec = new ArrayList<>(patterns);
|
||||||
@ -386,32 +401,28 @@ public class ASTToTargetAST {
|
|||||||
TargetExpression expr = null;
|
TargetExpression expr = null;
|
||||||
var i = 0;
|
var i = 0;
|
||||||
for (var param : method.signature().parameters()) {
|
for (var param : method.signature().parameters()) {
|
||||||
if (param.pattern() instanceof TargetComplexPattern pat) {
|
if (i == offset) {
|
||||||
if (i == offset) {
|
patternsRec.add(param.pattern());
|
||||||
patternsRec.add(pat);
|
|
||||||
}
|
|
||||||
if (i > offset) {
|
|
||||||
// Find next pattern
|
|
||||||
var pattern = param.pattern();
|
|
||||||
expr = new TargetLocalVar(pattern.type(), pattern.name());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
|
if (i > offset) {
|
||||||
|
// Find next pattern
|
||||||
|
expr = params.get(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
var lastPattern = patternsRec.getLast();
|
var lastPattern = patternsRec.getLast();
|
||||||
if (usedPatterns.contains(lastPattern)) continue;
|
var type = unwrap(lastPattern.type());
|
||||||
usedPatterns.add(lastPattern);
|
if (usedPatterns.contains(type)) continue;
|
||||||
|
usedPatterns.add(type);
|
||||||
|
|
||||||
var candidates = methods.stream().filter(m -> {
|
var candidates = methods.stream().filter(m -> {
|
||||||
var j = 0;
|
var j = 0;
|
||||||
for (var param : m.signature().parameters()) {
|
for (var param : m.signature().parameters()) {
|
||||||
if (j >= patternsRec.size()) return true;
|
if (j >= patternsRec.size()) return true;
|
||||||
if (param.pattern() instanceof TargetComplexPattern) {
|
if (!patternsRec.get(j).type().equals(param.pattern().type())) return false;
|
||||||
if (!patternsRec.get(j).equals(param.pattern())) return false;
|
j++;
|
||||||
j++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}).toList();
|
}).toList();
|
||||||
@ -430,6 +441,7 @@ public class ASTToTargetAST {
|
|||||||
if (overloadedMethods.size() <= 1) return overloadedMethods;
|
if (overloadedMethods.size() <= 1) return overloadedMethods;
|
||||||
// Check if we have a pattern as a parameter
|
// Check if we have a pattern as a parameter
|
||||||
var firstMethod = overloadedMethods.getFirst();
|
var firstMethod = overloadedMethods.getFirst();
|
||||||
|
var secondMethod = overloadedMethods.get(1);
|
||||||
if (firstMethod.signature().parameters().stream().noneMatch(mp -> mp.pattern() instanceof TargetComplexPattern)) return overloadedMethods;
|
if (firstMethod.signature().parameters().stream().noneMatch(mp -> mp.pattern() instanceof TargetComplexPattern)) return overloadedMethods;
|
||||||
// Rename existing methods
|
// Rename existing methods
|
||||||
|
|
||||||
@ -439,23 +451,41 @@ public class ASTToTargetAST {
|
|||||||
res.add(new TargetMethod(method.access(), name, method.block(), method.signature(), method.txSignature()));
|
res.add(new TargetMethod(method.access(), name, method.block(), method.signature(), method.txSignature()));
|
||||||
}
|
}
|
||||||
|
|
||||||
var signatureParams = firstMethod.signature().parameters().stream().map(p -> {
|
var signatureParams = new ArrayList<MethodParameter>();
|
||||||
if (p.pattern() instanceof TargetComplexPattern pat) {
|
for (var i = 0; i < firstMethod.signature().parameters().size(); i++) {
|
||||||
return new MethodParameter(pat.type(), pat.name());
|
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().parameters().get(i).pattern().type();
|
||||||
|
commonSubTypes.retainAll(commonSuperInterfaceTypes(t1, t3));
|
||||||
}
|
}
|
||||||
return p;
|
if (commonSubTypes.size() != 1) throw new DebugException("Invalid overload");
|
||||||
}).toList();
|
// TODO accept multiple types
|
||||||
var parameters = firstMethod.signature().parameters().stream().map( p -> (TargetExpression) new TargetLocalVar(p.pattern().type(), p.pattern().name())).toList();
|
var 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));
|
||||||
|
}
|
||||||
|
|
||||||
|
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().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 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());
|
||||||
var firstPattern = firstMethod.signature().parameters().stream().filter(p -> p.pattern() instanceof TargetComplexPattern).findFirst().orElseThrow().pattern();
|
|
||||||
|
|
||||||
// Generate dispatch method
|
// Generate dispatch method
|
||||||
var classType = new TargetRefType(clazz.getClassName().getClassName());
|
var classType = new TargetRefType(clazz.getClassName().getClassName());
|
||||||
var stmt = generatePatternOverloadsRec(0, new TargetLocalVar(firstPattern.type(), firstPattern.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 signature = new TargetMethod.Signature(firstMethod.signature().generics(), signatureParams, firstMethod.signature().returnType());
|
var signature = new TargetMethod.Signature(Set.of(), signatureParams, returnType);
|
||||||
var bridgeMethod = new TargetMethod(firstMethod.access(), firstMethod.name(), block, signature, firstMethod.txSignature());
|
var bridgeMethod = new TargetMethod(firstMethod.access(), firstMethod.name(), block, signature, firstMethod.txSignature());
|
||||||
|
|
||||||
res.add(bridgeMethod);
|
res.add(bridgeMethod);
|
||||||
|
@ -118,7 +118,7 @@ public class TYPE {
|
|||||||
FormalParameter param = (FormalParameter) allClass.getConstructors().getFirst().getParameterList().getParameterAt(counter);
|
FormalParameter param = (FormalParameter) allClass.getConstructors().getFirst().getParameterList().getParameterAt(counter);
|
||||||
FieldAssumption assumption = new FieldAssumption(param.getName(), allClass, param.getType(), blockInformation.getCurrentTypeScope());
|
FieldAssumption assumption = new FieldAssumption(param.getName(), allClass, param.getType(), blockInformation.getCurrentTypeScope());
|
||||||
|
|
||||||
var fieldCons = new Pair(el.getType(), assumption.getType(resolver), PairOperator.SMALLERDOT);
|
var fieldCons = new Pair(el.getType(), assumption.getType(resolver), PairOperator.EQUALSDOT);
|
||||||
var recvCons = new Pair(refType, assumption.getReceiverType(resolver), PairOperator.EQUALSDOT);
|
var recvCons = new Pair(refType, assumption.getReceiverType(resolver), PairOperator.EQUALSDOT);
|
||||||
constraintSet.addUndConstraint(fieldCons);
|
constraintSet.addUndConstraint(fieldCons);
|
||||||
constraintSet.addUndConstraint(recvCons);
|
constraintSet.addUndConstraint(recvCons);
|
||||||
|
@ -930,6 +930,16 @@ public class TestComplete {
|
|||||||
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "PatternMatchingListAppend.jav");
|
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "PatternMatchingListAppend.jav");
|
||||||
var clazz = classFiles.get("PatternMatchingListAppend");
|
var clazz = classFiles.get("PatternMatchingListAppend");
|
||||||
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())));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
Loading…
Reference in New Issue
Block a user