Work on overloading
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 47s

This commit is contained in:
Daniel Holle 2024-11-19 13:32:55 +01:00
parent bb11d24101
commit 88d81f4af7
2 changed files with 81 additions and 29 deletions

View File

@ -5,11 +5,19 @@ import java.lang.Float;
public record Point(Number x, Number y) {} public record Point(Number x, Number y) {}
public class OverloadPattern { public class OverloadPattern {
public Number m(Point(Integer x, Integer y)) { public Number m(Point(Integer x, Integer y), Point(Float a, Float b)) {
return x + y; return x + y;
} }
public Number m(Point(Float x, Float y)) { public Number m(Point(Integer x, Integer y), Point(Integer a, Integer b)) {
return x + y;
}
public Number m(Point(Float x, Float y), Point(Integer a, Integer b)) {
return x * y;
}
public Number m(Point(Float x, Float y), Point(Float a, Float b)) {
return x * y; return x * y;
} }

View File

@ -5,6 +5,7 @@ import de.dhbwstuttgart.bytecode.FunNGenerator;
import de.dhbwstuttgart.core.JavaTXCompiler; import de.dhbwstuttgart.core.JavaTXCompiler;
import de.dhbwstuttgart.environment.ByteArrayClassLoader; import de.dhbwstuttgart.environment.ByteArrayClassLoader;
import de.dhbwstuttgart.environment.IByteArrayClassLoader; import de.dhbwstuttgart.environment.IByteArrayClassLoader;
import de.dhbwstuttgart.exceptions.DebugException;
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.*;
@ -318,6 +319,63 @@ public class ASTToTargetAST {
} }
} }
private TargetExpression generatePatternOverloadsRec(int offset, TargetExpression switchExpr, List<TargetExpression> params, List<TargetComplexPattern> 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();
TargetExpression caseBody = new TargetMethodCall(
method.signature().returnType(),
new TargetThis(classType),
params,
classType,
method.name(),
false, false, method.isPrivate()
);
if (method.signature().returnType() != null) {
caseBody = new TargetReturn(caseBody);
}
return caseBody;
}
var cases = new ArrayList<TargetSwitch.Case>();
for (var method : methods) {
var patternsRec = new ArrayList<>(patterns);
var i = 0;
for (var param : method.signature().parameters()) {
if (param.pattern() instanceof TargetComplexPattern pat) {
if (i == offset) {
patternsRec.add(pat);
break;
}
i++;
}
}
var candidates = methods.stream().filter(m -> {
var j = 0;
for (var param : m.signature().parameters()) {
if (j >= patternsRec.size()) return true;
if (param.pattern() instanceof TargetComplexPattern) {
if (!patternsRec.get(j).equals(param.pattern())) return false;
j++;
}
}
return true;
}).toList();
var last = patternsRec.getLast();
var expr = new TargetLocalVar(last.type(), last.name());
var caseBody = generatePatternOverloadsRec(offset + 1, expr, params, patternsRec, candidates, classType);
var body = new TargetBlock(List.of(caseBody));
var case_ = new TargetSwitch.Case(List.of(method.signature().parameters().getFirst().pattern()), body);
cases.add(case_);
}
return new TargetSwitch(switchExpr, cases, null);
}
private List<TargetMethod> generatePatternOverloads(ClassOrInterface clazz, List<TargetMethod> overloadedMethods) { private List<TargetMethod> generatePatternOverloads(ClassOrInterface clazz, List<TargetMethod> overloadedMethods) {
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
@ -331,37 +389,23 @@ 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()));
} }
// Generate dispatch method var signatureParams = firstMethod.signature().parameters().stream().map(p -> {
var firstParam = firstMethod.signature().parameters().get(0); if (p.pattern() instanceof TargetComplexPattern pat) {
var cases = new ArrayList<TargetSwitch.Case>(); return new MethodParameter(pat.type(), pat.name());
TargetExpression expr = new TargetLocalVar(firstParam.pattern().type(), firstParam.pattern().name());
var classType = new TargetRefType(clazz.getClassName().getClassName());
for (var method : res) {
TargetExpression caseBody = new TargetMethodCall(
method.signature().returnType(),
new TargetThis(classType),
List.of(expr),
classType,
method.name(),
false, false, method.isPrivate()
);
if (method.signature().returnType() != null) {
caseBody = new TargetReturn(caseBody);
} }
var body = new TargetBlock(List.of(caseBody)); return p;
var case_ = new TargetSwitch.Case(List.of(method.signature().parameters().getFirst().pattern()), body); }).toList();
var parameters = firstMethod.signature().parameters().stream().map( p -> (TargetExpression) new TargetLocalVar(p.pattern().type(), p.pattern().name())).toList();
//var patterns = List.of((TargetComplexPattern) firstMethod.signature().parameters().stream()
// .filter(p -> p.pattern() instanceof TargetComplexPattern).findFirst().orElseThrow().pattern());
var firstPattern = firstMethod.signature().parameters().stream().filter(p -> p.pattern() instanceof TargetComplexPattern).findFirst().orElseThrow().pattern();
cases.add(case_); // Generate dispatch method
} var classType = new TargetRefType(clazz.getClassName().getClassName());
var stmt = generatePatternOverloadsRec(0, new TargetLocalVar(firstPattern.type(), firstPattern.name()), parameters, List.of(), res, classType);
var stmt = new TargetSwitch(expr, cases, null);
var block = new TargetBlock(List.of(stmt)); var block = new TargetBlock(List.of(stmt));
var parameters = List.of(new MethodParameter(firstParam.pattern().type(), firstParam.pattern().name())); var signature = new TargetMethod.Signature(firstMethod.signature().generics(), signatureParams, firstMethod.signature().returnType());
var signature = new TargetMethod.Signature(firstMethod.signature().generics(), parameters, firstMethod.signature().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);