Lyx unterstützt die volle rekursive Funktionsaufrufe. Da der Compiler die Standard Linux x86_64 SysV ABI implementiert, nutzt jeder Aufruf den Hardware-Stack, um Rücksprungadressen und lokale Variablen (Stack-Frames) sicher zu verwalten.
Eine Funktion wird als rekursiv bezeichnet, wenn sie sich innerhalb ihres eigenen Körpers selbst aufruft. In Lyx erfordert eine saubere Rekursion zwei Bestandteile:
Die mathematische Fakultät (n!) ist das klassische Beispiel für Rekursion:
fn Factorial(n: int64): int64 {
// 1. Abbruchbedingung
if (n <= 1) {
return 1;
}
// 2. Rekursiver Schritt
return n * Factorial(n - 1);
}
fn Main(): int64 {
var result: int64 := Factorial(5);
PrintStr("5! ist: ");
PrintInt(result); // Ausgabe: 120
return 0;
}
Bei jedem rekursiven Aufruf erzeugt das Backend einen neuen Stack-Frame. Dies garantiert, dass jede Instanz der Funktion ihre eigenen lokalen Variablen besitzt.
| Schritt | Aktion im Backend | Register / Stack |
|---|---|---|
| Proloque | Sichern des alten Base-Pointers | `push rbp`, `mov rbp, rsp` |
| Arguments | Parameter für den nächsten Aufruf setzen | `mov rdi, [new_val]` |
| Call | Rücksprungadresse speichern & springen | `call Factorial` |
| Epilogue | Stack aufräumen & zurückkehren | `leave`, `ret` |
| Feature | Status | Beschreibung |
|---|---|---|
| Hardware-Stack | ✅ Aktiv | Volle Nutzung des RSP-Registers. |
| Register-Safety | ✅ Aktiv | Caller-saved Register werden vor dem Aufruf gesichert. |
| Tail-Call Opt. | 🚧 Geplant | Aktuell wird für jeden Aufruf ein neuer Frame erzeugt (keine Ersetzung). |
Mit der Einführung von Klassen können nun rekursive Methoden auf Objekten definiert werden, was ideal für Baumstrukturen oder verkettete Listen ist.
type Node = class {
Value: int64;
Next: Node?; // Nullable Pointer
fn PrintAll() {
PrintInt(self.Value);
PrintStr(" ");
// Rekursiver Aufruf auf das nächste Element
if (self.Next != null) {
self.Next?.PrintAll();
}
}
};
Verwandte Themen: