diff --git a/resources/bytecode/javFiles/OverloadPattern.jav b/resources/bytecode/javFiles/OverloadPattern.jav index 117600f5..515d5f85 100644 --- a/resources/bytecode/javFiles/OverloadPattern.jav +++ b/resources/bytecode/javFiles/OverloadPattern.jav @@ -5,11 +5,19 @@ import java.lang.Float; public record Point(Number x, Number y) {} 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; } - 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; } diff --git a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java index 8b515c93..bcd54df1 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java @@ -5,6 +5,7 @@ import de.dhbwstuttgart.bytecode.FunNGenerator; import de.dhbwstuttgart.core.JavaTXCompiler; import de.dhbwstuttgart.environment.ByteArrayClassLoader; import de.dhbwstuttgart.environment.IByteArrayClassLoader; +import de.dhbwstuttgart.exceptions.DebugException; import de.dhbwstuttgart.parser.NullToken; import de.dhbwstuttgart.parser.scope.JavaClassName; import de.dhbwstuttgart.syntaxtree.*; @@ -318,6 +319,63 @@ public class ASTToTargetAST { } } + private TargetExpression generatePatternOverloadsRec(int offset, TargetExpression switchExpr, List params, List patterns, List 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(); + 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 generatePatternOverloads(ClassOrInterface clazz, List overloadedMethods) { if (overloadedMethods.size() <= 1) return overloadedMethods; // 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())); } - // Generate dispatch method - var firstParam = firstMethod.signature().parameters().get(0); - var cases = new ArrayList(); - 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 signatureParams = firstMethod.signature().parameters().stream().map(p -> { + if (p.pattern() instanceof TargetComplexPattern pat) { + return new MethodParameter(pat.type(), pat.name()); } - var body = new TargetBlock(List.of(caseBody)); - var case_ = new TargetSwitch.Case(List.of(method.signature().parameters().getFirst().pattern()), body); + return p; + }).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_); - } - - var stmt = new TargetSwitch(expr, cases, null); + // 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 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(), parameters, firstMethod.signature().returnType()); + var signature = new TargetMethod.Signature(firstMethod.signature().generics(), signatureParams, firstMethod.signature().returnType()); var bridgeMethod = new TargetMethod(firstMethod.access(), firstMethod.name(), block, signature, firstMethod.txSignature()); res.add(bridgeMethod);