Inhaltsverzeichnis

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:

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


Verwandte Themen: