\*\*\* \# Projekt-Protokoll: Weiterentwicklung des Sprachdesigns \* \*\*Datum:\*\* 08. Oktober 2025 \* \*\*Zeit:\*\* 13:22 CEST \## Motivation Die bestehende Skriptsprache bietet grundlegende funktionale und imperative Konstrukte, aber die Verwaltung von veränderlichem Zustand (`def` in Verbindung mit `assign`) ist unsicher, insbesondere im Hinblick auf Nebenläufigkeit. Das primäre Motiv für eine Weiterentwicklung ist die Schaffung einer Sprache, die \*\*aus sich selbst heraus sicher ("safe by design")\*\* ist, ohne dabei die Komplexität von Low-Level-Konzepten wie manueller Speicherverwaltung oder einem vollständigen Borrow-Checker (wie in Rust) einzuführen. Die Sprache soll auch für Programmier-Anfänger \*\*intuitiv und leicht verständlich\*\* bleiben. \## Ziel Das Ziel ist es, ein Sprachdesign zu entwickeln, das eine klare und sichere Handhabung von Zustand erzwingt. Die Kernziele des neuen Designs sind: 1\. \*\*Sicherheit durch Design:\*\* Race Conditions durch geteilten, veränderlichen Zustand sollen zur Compile-Zeit erkannt und verhindert werden. 2\. \*\*Klare Trennung von Zustandsarten:\*\* Es soll eine unmissverständliche Unterscheidung zwischen temporärem, lokalem Zustand und persistentem, geteiltem Zustand geben. 3\. \*\*Intuitive Semantik:\*\* Die Regeln der Sprache sollen den Entwickler aktiv zu sicheren und korrekten Mustern anleiten ("Pit of Success"). "Magisches" oder unvorhersehbares Verhalten des Compilers soll vermieden werden. 4\. \*\*Pragmatismus:\*\* Ein bekannter, imperativer Programmierstil soll für lokale Logik weiterhin möglich sein, um die Lernkurve flach zu halten. \## Ergebnis: Das finale Sprachdesign Wir haben uns auf ein pragmatisches Hybrid-Modell geeinigt, das funktionale Sicherheit mit imperativem Komfort kombiniert. Es basiert auf drei Säulen: \### 1. Sicherer globaler Zustand: `def` erzeugt Atome Der `def`-Befehl wird modifiziert. Er dient ausschließlich zur Definition von Zustand, der potenziell über Funktionsgrenzen hinweg geteilt wird. Um dies von Natur aus sicher zu machen, erzeugt `def` nicht mehr einen einfachen, veränderlichen "Slot", sondern immer einen \*\*atomaren Container\*\*, der den Wert umschließt. Jede Zustandsänderung muss über explizite, threadsichere atomare Operationen (wie `swap!` oder `reset!`) erfolgen. Dies eliminiert alle Race Conditions bei globalem Zustand. \### 2. Veränderlicher lokaler Zustand: `let` mit `assign` Ein neues `let`-Konstrukt wird eingeführt, das sich an Clojure orientiert, um einen neuen lexikalischen Gültigkeitsbereich zu schaffen. Im Gegensatz zu Clojure sind die in `let` definierten Bindungen jedoch \*\*standardmäßig veränderlich\*\* und können über `assign` modifiziert werden. Dies erlaubt Entwicklern, für rein lokale Algorithmen (z.B. Schleifen mit Zählern) einen vertrauten, imperativen Stil zu verwenden, wo Threadsicherheit keine Rolle spielt. \### 3. Die Sicherheitsbrücke: Statische Analyse im Binder Dies ist die zentrale Innovation, die beide Welten sicher miteinander verbindet. Der Compiler (speziell der Binder) führt eine \*\*Escape Analysis\*\* für Closures durch, um die missbräuchliche Freigabe von unsicherem, lokalem Zustand zu verhindern. Dabei gilt eine einzige, einfache Regel: > \*\*Eine Closure, die eine veränderliche let-Variable fängt, darf nicht aus dem Gültigkeitsbereich der Funktion zurückgegeben (oder global gespeichert) werden, in der diese Variable definiert wurde.\*\* \* Wenn eine solche "zustandsbehaftete" Closure nur lokal verwendet wird (z.B. in einem `Map`), ist der Code gültig. \* Wenn versucht wird, eine solche Closure zurückzugeben oder einem globalen `def` zuzuweisen, erzeugt der Binder einen \*\*Compile-Fehler\*\*. Dieser Fehler ist ein Feature, kein Mangel. Er zwingt den Entwickler, eine bewusste Entscheidung zu treffen: Entweder er strukturiert seinen Code um, oder er verwendet für den Zustand, der geteilt werden muss, explizit ein sicheres Primitiv (indem er die lokale Variable selbst zu einem `(atom ...)` macht). Dieses Design vermeidet die Komplexität eines Borrow Checkers und die Unvorhersehbarkeit von "Compiler-Magie", indem es eine klare, leicht verständliche Regel zur Compile-Zeit durchsetzt. --- \## Nächste Schritte (Todo) 1\. \*\*Binder anpassen:\*\* Implementierung der Escape Analysis für Closures. Der Binder muss `let`-Variablen, ihre Veränderung durch `assign` und das Fangen durch Closures nachverfolgen. 2\. \*\*Parser erweitern:\*\* Hinzufügen der Syntax für das neue `let`-Statement. 3\. \*\*`def`-Implementierung ändern:\*\* Die Laufzeitlogik für `def` muss so angepasst werden, dass sie atomare Container anstelle von rohen Werten verwaltet. 4\. \*\*RTL erweitern:\*\* Die Laufzeit-Bibliothek muss um Funktionen zur Interaktion mit Atomen erweitert werden (z.B. `atom`, `deref`, `swap!`, `reset!`). 5\. \*\*Compiler-Fehlermeldung implementieren:\*\* Eine klare und hilfreiche Fehlermeldung für den Fall entwerfen, dass die "Sicherheitsbrücke"-Regel verletzt wird.