Bridge-Methode für Pattern Matching in Funktionsköpfen #355
Labels
No Label
Codegen
confirmed
duplicate
Eclipse-Plugin
Feature Request
generics
in progress
invalid
JavaCompilerCore
needs info
Parser
Trash
Type
Unify
won't fix
works for me
No Milestone
No project
2 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: JavaTX/JavaCompilerCore#355
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Das Pattern-Matching in Funktionsköpfen soll das unter Java verwendete Visitor-Pattern ersetzen.
Hierzu folgendes Beispiel:
Bislang werden nur Überladungen für die einzelnen Funktionen erstellt. Da Java aber kein multiple dispatch auf Funktionsargumente implementiert ist dies hier nicht zielführend.
Java braucht eine Bridge-Methode welche als erstes Argument
List
übergeben bekommt. Diese muss vom Compiler generiert werden.Da hier konkrete Typen verwendet werden (
Cons
&Empty
) taucht der TypList
im Result-Set allerdings nicht auf.Um das Ganze umzusetzen muss für das erste Argument zunächst ein Supertyp gefunden werden. Die Methoden mit der selben Signatur (
append
) werden hier zusammengefasst. Der Supertyp muss ein sealed Interface sein und alle Fälle (siehe permits-Klausel) müssen abgedeckt werden. Nur wenn dies der Fall ist kann eine Bridge-Methode erstellt werden.Die Bridge-Methode besteht dann aus einem switch-Statement welches zur Laufzeit die Typen überprüft und die richtige Implementierung aufruft.
Ein mögliches Problem bei der Umsetzung könnte sein, dass die Typinferenz nichts von der Bridge-Methode weiß und diese deshalb nicht aufrufen kann.
Ich habe mich jetzt mal dran gesetzt und ein weiteres Problem gefunden.
Hier werden von der Typinferenz 6 Methoden generiert:
Wenn ich jeweils nach einem Super-Interface suche sieht die Gruppierung so aus:
Für das richtige Ergebnis müssten allerdings alle diese Methoden in die selbe Gruppe kommen.
Object entspricht ja beim zweiten Parameter dem "default"-Fall. Ich weiß allerdings nicht wie ich das erkennen soll.
@pl Hast du da eine Idee?
Die Gruppierung war falsch, Object & Object sind logischerweise auch gleich (In diesem Fall hat es nicht geklappt weil beides Generics waren).
Jetzt gibt es allerdings wieder das gleiche Problem.
Meiner Meinung nach braucht man hier auch nur die Gruppe 1, Gruppe 2 ist komplett unnötig.
Hier würden dann zwei Bridge-Methoden generiert werden:
Das könnte vielleicht funktionieren. Generics fallen leider komplett raus, keine Ahnung wie ich die generieren soll.
Ich schlage folgende Änderungen vor
public append(Cons(a, b), list2) {
return new Cons<>(a, append(b, list2));
}
In AbsSyn:
TPH AQ append(Cons(TPH AR a, TPH AS b), TPH AU list2)({
return new Cons((a)::TPH AR, ((this)::TPH AW.append Signature: [TPH AX, TPH AY, TPH AZ]((b)::TPH AS, (list2)::TPH AU))::TPH BA);
})::TPH BF
AR und AS müssen Typen bekommen:
AR = AT (folgt aus der Def von Cons)
AS = List (folgt aus der Def von Cons)
append in den Assumptions jetzt den Typ (Cons, AU) -> AQ
sollte den Typ (AFresh, AU) -> AQ bekommen
Zusätzlich werden die Constraints
AFresh <. List (List kommt aus der implements Deklaration im Record) und
Cons <. AFresh
hinzugefügt
Ich bekomme jetzt folgendes Ergebnis:
Sieht das richtig aus?
Die Constraints sind hier:
AST:
Result:
Ich pushe mal, der Bytecode ist sowieso nicht valide weil die Bridge-Methoden fehlen.
Zile wäre:
Das Ergebis ist fast richtig:
[(TPH ACG = GTV T), (TPH ACI = GTV T), (TPH AQ = Cons), (TPH BI = Empty), (TPH AU = Empty), (TPH AC = Cons), (TPH AFO, TPH AFJ), (TPH BG = Empty), (TPH BD = List), (TPH AFL, TPH AFI), (TPH ACL, TPH AFI), (TPH AS = ? extends Empty), (TPH AR < TPH AFI), (TPH AR < TPH AFJ), (TPH AT, TPH AFJ), (TPH BC = GTV T), (TPH AFN = GTV T), (TPH BA = Empty), (TPH AFM = GTV T), (TPH AA = Cons), (TPH AZ = Empty), (TPH AY = Empty), (TPH AX = Empty), (TPH AW = PatternMatchingListAppend), (TPH AFK, TPH AFI), (TPH ACK, TPH AFJ), (TPH BE = Cons)],
[(TPH BC = GTV T), (TPH AFQ = GTV T), (TPH AR < TPH AFJ), (TPH AFP, TPH AFH), (TPH BE = Cons), (TPH BA = Cons), (TPH AR < TPH AFH), (TPH AFR = GTV T), (TPH AS = ? extends Empty), (TPH AX = Empty), (TPH AA = Cons), (TPH AY = Cons), (TPH ACG = GTV T), (TPH AFS, TPH AFJ), (TPH AZ = Cons), (TPH AFG, TPH AFH), (TPH ACK, TPH AFJ), (TPH BI = Cons), (TPH AC = Cons), (TPH ACI = GTV T), (TPH BD = List), (TPH AU = Cons), (TPH AT, TPH AFJ), (TPH AQ = Cons), (TPH AW = PatternMatchingListAppend), (TPH ACL, TPH AFH), (TPH BG = Cons)],
[(TPH AFX, TPH AFT), (TPH BC = GTV T), (TPH AC = Cons), (TPH ACI = GTV T), (TPH AFW, TPH ACK), (TPH ACG = GTV T), (TPH AQ = Cons), (TPH ACL, TPH AFT), (TPH BE = Cons), (TPH AW = PatternMatchingListAppend), (TPH BD = List), (TPH AA = Cons), (TPH AZ = Cons), (TPH BI < TPH BG), (TPH AR < TPH ACK), (TPH AX = Cons), (TPH AT, TPH ACK), (TPH AY, TPH AU), (TPH AFV = GTV T), (TPH AS = ? extends Cons), (TPH BA = Cons), (TPH AFU = GTV T), (TPH AR < TPH AFT)]]
Nur TPH AS = ? extends Empty), TPH AS = ? extends Cons sind die Wildcards falsch.
Hier muss beim generieren der TPHs wildcardable aof false setzt werden.
Das Ergebnis ist dann
Die Fälle mit Object sind also doch richtig?
Ja, ich bin zu neuen Einsichten gekommen, melde mich später
Ich meine es kann so auch noch nicht funktionieren:
Die Funktion führt sich ja selbst rekursiv auf, es gibt aber keine Funktion
welche die Rekursion terminieren würde.
Außerdem müsste diese Funktion
Cons
zurückgeben und nicht Object.Also insgesamt:
Ich glaube das würde wirklich alle Fälle abdecken.
Also im Prinzip gibt es drei verschiedene Fälle:
und generiert wird noch: