Nachdem ich erarbeitet hatte, dass eine technische Realisierung eines C++ Skripts, welches den vollen Feature Umfang und die komplette Syntax von modernen C++ unterstützt, zurzeit vollständig unklar oder viel zu komplex ist (siehe mein Blog Post), habe ich diese Aufgabe erst einmal auf unbestimmte Zeit nach hinten verschoben.
Stattdessen habe ich mir angeschaut wie man C++ Software skriptbar machen kann, da ich mir sehr sicher war und immer noch bin, dass man dieses benötigt und es viele Anwendungsfälle dafür gibt. Dies ist so, da C++ streng statisch typisiert zur Compile-Zeit ist, was zwar generell gut ist, aber zu wenig Flexibilität für dynamische Erweiterungen zur Laufzeit führt. Die Last des Kompilierens, Testens und Ausrollens von „Allem“ ist sehr hoch, wenn man nur eine klitzekleine Stelle der Anwendung verändern möchte.
(Update) Die Idee ist also, dass man 1 bis N Erweiterungspunkte in der C++ Anwendung hat, welche durch eine Skript-Datei zur Laufzeit ergänzt werden können. Damit muss die Anwendung nicht neu kompiliert und ausgerollt werden, sondern nur der kleine Skript-Teil modifiziert. Mehr auf der Hauptseite unter „In aller Kürze“.
Nach meiner Recherche habe ich herausgefunden, dass es nur 2 verfügbare Optionen gibt, die es Wert sind erwähnt zu werden. Es muss eine Skriptsprache sein, die als C++ Bibliothek verfügbar ist und die man ohne vorhergehende Installation oder Einrichtung auf dem Zielsystem nutzen kann.
Sol2 / Lua
Eine Option ist sol2 (https://github.com/ThePhD/sol2) von ThePhD (https://thephd.dev/), was Lua als Skriptsprache verwendet (https://www.lua.org/home.html).
Während aus meiner Sicht sol2 als C++ Bibliothek großartig aus der API Perspektive ist (aber auch komplex), habe ich wirkliche Bedenken Lua für einen größeren Nutzerkreis einzusetzen, der nicht unbedingt aus Entwicklungsexperten besteht und/oder vertraut mit Lua ist.
Die Lua Syntax ist bei einigen Aspekten nicht einfach, z.B. sind Chunk-Grenzen auch lediglich über ein Leerzeichen als Trenner möglich (https://www.lua.org/pil/1.1.html).
a = 1 b = a*2 -- ugly, but valid
Ein weiteres Beispiel ist, dass in Lua der Wert 0
(Null) als true
und nicht false
interpretiert wird (https://www.lua.org/pil/2.2.html). Dadurch kann es zu unerwarteten und großen Überraschungen kommen, wenn man noch nicht mit Lua vertraut ist.
Zusätzlich ist die Syntax sehr weit entfernt von C++ und die Kernsprachfeatures sind ebenso in vielen Dingen unterschiedlich, was nicht generell schlecht ist, aber durchaus relevant sein könnte, wenn man C++ Entwickler ansprechen möchte.
Natürlich gibt es außer den paar genannten noch mehr Sachen, die man ansprechen könnte, aber ich möchte an dieser Stelle nicht zu tief in Lua-spezifische Details einsteigen. Für interessierte Leser ist unter dem Lua-Link oben eine sehr detaillierte Dokumentation verfügbar. Es mag von Interesse sein – für mich war es das – dort mehr über die Lua Programmiersprache zu erfahren.
ChaiScript
Die zweite Option ist ChaiScript (https://chaiscript.com/index.html) von Jason Turner (https://www.youtube.com/watch?v=CeHSHEZg-PQ) und seinem Bruder Jonathan Turner.
Alles in allem ist ChaiScript wirklich großartig. Insbesondere die Typ-Konvertierungen sowie die Abfertigung von Funktionsaufrufen und die Überladungsauflösung sind wirklich stark implementiert und reich an Features. Um ehrlich zu sein weiß ich aktuell noch nicht, ob ich mit TeaScript das gleiche Level erreiche (nur diesen Aspekt der Sprache betrachtet!). TeaScript hat einen stärkeren Fokus auf andere Aspekte. Mehr dazu später.
Aber ChaiScript hat auch Nachteile und Dinge, die anders und besser gemacht werden können. Zusätzlich habe ich viele Sprachfeatures im Sinn, welche in ChaiScript gar nicht vorhanden sind.
Neben einigen Kleinigkeiten (z.B.: obgleich „header only“ Bibliotheken wirklich großartig wegen der einfachen Benutzbarkeit sind, denke ich, ist ChaiScript bereits viel zu groß um nur „header only“ zu sein) fehlen viele Features im Bereich der parallelen / multi-threading Ausführung sowie moderne Programmiersprachen Features. Man kann sehr einfach erkennen, dass ChaiScript bereits ein wenig veraltet ist und die Features entworfen wurden als C++11 aktuell war (oder sogar davor). In der Zwischenzeit hat sich nicht nur C++ weiterentwickelt, sondern es gibt auch eine ganze Serie an komplett neuen Sprachen mit Tonnen an neuen und modernen Programmier-Features (insbesondere erwähnt sei hier Rust, Zig, Julia, Go und TypeScript).
Aber noch wichtiger ist, dass ich auch einige technische Probleme und Nachteile in der zugrunde liegenden Software-Architektur entdeckt habe. Die größten sind:
- Der Parser muss immer mit syntaktisch kompletten Blöcken gefüttert werden, also z.B. einen kompletten if-else-if-else Statement auf Top-Level Ebene mit dem gesamten inneren Content. Also ist das Beste, man füttert immer das gesamte Skript als Ganzes, welches dann auch in einem Rutsch geparsed wird. Aber dieser Ansatz macht einige Anwendungsfälle unmöglich oder ggf. unbenutzbar in der Praxis (z.B., wenn das Skript noch nicht als Ganzes verfügbar ist oder bei anderen Szenarien mit teilweisem Parsen/Evaluieren.).
- Es verwendet einen rekursiven Ansatz für die AST-Evaluierung (Abstract Syntax Tree). Dies ist nicht notwendigerweise ein Problem, wenn man nur das gesamte Skript ausführen möchte, aber es wird zu einem echten Problem und könnte unmöglich zu realisieren sein, wenn man das Skript mitten in der Ausführung anhalten und zu einem späteren Zeitpunkt an exakt derselben Stelle im selben Zustand weiterlaufen lassen möchte.
TeaScript wird all diese Dinge und Probleme adressieren, insbesondere wird es eine andere zugrunde liegende Software Architektur nutzen um die technischen Nachteile erst gar nicht zu haben.
Bezüglich der technischen Aspekte des Parsens von Skript-Code und der AST-Evaluierung folgen demnächst von Zeit zu Zeit einige Blog Posts.
Fazit
Insgesamt bin ich zu dem Schluss gekommen, dass es Bedarf und auch Platz für eine dritte Option gibt. Aus diesem Grund habe ich mich entschieden TeaScript zu entwerfen und zu realisieren um diesen Punkt zu adressieren.
Als nächstes: Ziele und Features von TeaScript.