Compiler-Interna
Die wichtigsten Designentscheidungen, die Perry schnell machen
01NaN-Boxing
Werte werden als 64-Bit-Floats mit speziellen Bitmustern für Pointer gespeichert, wodurch Union-Typen ohne Laufzeit-Overhead möglich sind. So funktioniert (string | number)[] effizient.
Durch die Kodierung von Typinformationen direkt in den IEEE-754-NaN-Payload-Bits vermeidet Perry den Bedarf an Tagged Unions oder Boxed Values. Ein einzelnes 64-Bit-Wort kann jeden JavaScript-Werttyp darstellen — Zahlen nutzen ihre natürliche Darstellung, während Strings, Objekte und andere heap-allokierte Werte Pointer-Bitmuster verwenden, die im NaN-Bereich liegen.
02Monomorphization
Generics werden zur Compile-Zeit spezialisiert, wie in Rust. Jede Typinstanziierung erzeugt optimierten Code und eliminiert den Overhead von Laufzeit-Typprüfungen.
Wenn du Array'<'number'>' und Array'<'string'>' schreibst, generiert Perry zwei separate, vollständig optimierte Implementierungen. Das bedeutet, Array-Operationen auf Zahlen nutzen direkte Maschinenarithmetik — keine Type Guards, kein Dynamic Dispatch, kein Boxing.
03Static Dispatch
Keine virtuellen Tabellen. Methodenaufrufe werden zur Compile-Zeit aufgelöst, was direkte Funktionsaufrufe und Inlining-Optimierungen ermöglicht.
Traditionelle OOP-Laufzeitumgebungen nutzen VTables zur Methodenauflösung und fügen bei jedem Aufruf eine Indirektionsebene hinzu. Perry löst alle Methodenaufrufe statisch während der Kompilierung auf und verwandelt Interface-Methodenaufrufe in direkte Sprünge. Das ermöglicht auch aggressives Inlining — kleine Methoden werden oft direkt in ihre Aufrufstellen eingebettet.
04Zero-Cost Abstractions
TypeScript-Klassen, Interfaces und Generics kompilieren zu effizientem nativem Code ohne Overhead durch Laufzeitdarstellung.
TypeScripts Typsystem existiert nur zur Compile-Zeit — und Perry nimmt das wörtlich. Interfaces erzeugen keinen Laufzeit-Code. Klassenhierarchien werden abgeflacht. Generische Einschränkungen werden zu konkreten Typen aufgelöst. Das kompilierte Binary enthält nur die tatsächliche Logik, ohne den Abstraktionsapparat, den Interpreter typischerweise mitbringen.