====== Lyx – Rekursion ====== 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. ---- ===== 1) Grundlagen ===== Eine Funktion wird als rekursiv bezeichnet, wenn sie sich innerhalb ihres eigenen Körpers selbst aufruft. In Lyx erfordert eine saubere Rekursion zwei Bestandteile: * **Abbruchbedingung (Base Case):** Ein Pfad, der keinen weiteren rekursiven Aufruf tätigt. * **Rekursionsschritt:** Der Aufruf der Funktion mit veränderten Argumenten, die dem Base Case näher kommen. ==== Beispiel: Fakultät (Factorial) ==== 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; } ---- ===== 2) Technische Implementierung ===== ==== Stack-Frame Management ==== 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` | ==== Status der Optimierung ==== ^ 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). | ---- ===== 3) Rekursion in Datenstrukturen (v0.1.7) ===== 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(); } } }; ---- ===== 4) Wichtige Hinweise & Limits ===== * **Stack Overflow:** Da Lyx keinen unendlichen Stack hat, führt eine zu tiefe Rekursion (oder eine fehlende Abbruchbedingung) zu einem **Segmentation Fault**. Das Limit liegt unter Linux standardmäßig bei 8 MB. * **Performance:** Rekursion ist elegant, aber für extrem einfache Aufgaben (wie bloßes Zählen) ist eine iterative Lösung (while-Schleife) effizienter, da der Overhead des Funktionsaufrufs entfällt. ---- **Verwandte Themen:** * [[lyx_-_programmiersprache:syntax|Lyx Syntax]] * [[lyx_-_programmiersprache:standard_library|Standard Library & Units]]