Die Veröffentlichung der Programmiersprache Nim in der Version 2.2.6 wurde vorgestellt. Das Update erschien sechs Monate nach der Veröffentlichung von Version 2.2.4 und umfasst 141 Commits mit Fehlerbehebungen und Leistungsverbesserungen. Nim ist eine statisch typisierte, kompilierbare Programmiersprache mit einer von Python inspirierten Syntax und Metaprogrammierungsfähigkeiten auf Lisp-Niveau. Die Sprache wird in C, C++ und JavaScript kompiliert und bietet C-Niveau an Leistung bei der Ausdruckskraft von höheren Programmiersprachen. Der Projektcode wird unter der MIT-Lizenz bereitgestellt.
Zu den wichtigsten Funktionen von Nim gehören ein leistungsstarkes Makrosystem, das zur Kompilierzeit auf dem AST arbeitet, ein ausgereiftes System für generische Programmierung mit Konzepten, multiple Dispatch, deterministische Speicherverwaltung mit Unterstützung mehrerer Strategien (ARC/ORC, refc, Mark and Sweep), eingebaute Unterstützung für async/await für asynchrones Programmieren und FFI für die einfache Integration mit C/C++/JavaScript. Nim wird als Systemsprache positioniert, die für die Entwicklung von eingebetteten Systemen bis zu Webanwendungen geeignet ist.Server, mit einem Fokus auf Effizienz, Speichersicherheit und Benutzerfreundlichkeit.
Wichtige Änderungen:
- Optimierung der Move-Semantik für Objektfelder. Der Compiler hat gelernt, die Möglichkeit der Anwendung von Move-Operationen bei der Rückgabe von Objektfeldern zu erkennen. Früher führten Konstruktionen wie „return obj.field“ zu einer Kopie der Daten, jetzt wendet der Compiler korrekt das Verschieben an: proc getField(obj: MyObject): string = return obj.field # Jetzt move statt copy
Dies ist besonders wichtig für große Datentypen (Strings, Sequenzen, ressourcenhaltige Objekte), bei denen die Beseitigung überflüssiger Kopiervorgänge einen spürbaren Leistungszuwachs bietet, ohne den Code zu verändern.
- Komplette Neugestaltung von Closure-Iteratoren mit Ausnahmebehandlung. Der Mechanismus zur Transformation von Closure-Iteratoren wurde vollständig neu geschrieben, was die Stabilität von Async-Code mit Ausnahmebehandlung erheblich verbessert hat. Kritische Probleme wurden behoben, einschließlich SIGSEGV bei Verwendung von try/except nicht auf oberster Ebene: iterator problematicIterator(): int {.closure.} = for i in 0..10: try: if i == 5: raise newException(ValueError, «test») yield i except ValueError: discard # Früher führte dies zu SIGSEGV
Ein weiteres Problem mit der fehlerhaften Weitergabe von Ausnahmen in finally-Blöcken innerhalb von Closure-Iteratoren wurde ebenfalls behoben.
- Fehlerbehebungen im Zusammenhang mit dem Speichermanagement
- Ein grundlegendes Problem im Garbage Collector wurde behoben, das beim Verarbeiten von zirkulären Datenstrukturen zu dem Fehler "Illegal storage access" führen konnte. Dieses Problem bestand seit der Einführung der Sprache und trat bei komplexen Objektgraphen mit gegenseitigen Verweisen auf.
- Der fehlerhafte Zerstörungsreihenfolge von Objekten wurde korrigiert, was dazu führen konnte, dass auf bereits freigegebenen Speicher zugegriffen wurde: type Resource = object data: ptr Data Container = object resource: Resource other: OtherResource # Jetzt werden die Destruktoren in der richtigen Reihenfolge aufgerufen: # zuerst other, dann resource
- Der ORC-Garbage Collector hat fälschlicherweise einige Umgebungen von Closures als zirkulär gekennzeichnet, was zu Verzögerungen bei der Speicherfreigabe oder zu Speicherlecks führte. Jetzt funktioniert die Zyklusanalyse korrekt.
- Ein Socket-Leck im asyncnet bei TLS-Verbindungsfehlern wurde behoben: proc handleClient() {.async.} = var socket = await server.accept() try: await socket.setupSSL() # Bei einem Fehler hier wird der Socket jetzt korrekt geschlossen except SSLError: discard # Der Socket leckt nicht mehr
- Kritische Fehlerbehebungen im Compiler.
- Ein Rückschritt wurde behoben, bei dem globale Variablen, die innerhalb von Prozeduren mit statischen Parametern deklariert wurden, bei jedem Aufruf neu initialisiert wurden: proc test[N: static int]() = var global {.global.}: array[N, int] global[0] += 1 echo global[0] test[5]() # Gab aus: 1 test[5]() # Sollte: 2 sein, gab aber: 1 aus (wurde neu initialisiert)
- Die Codegenerierung für globale Variablen in rekursiven Funktionen wurde korrigiert, die zu undefiniertem Verhalten führte.
- Ein altes Problem bei der Generierung von fehlerhaftem C-Code wurde gelöst, wenn Konstruktoren für globale Variablen innerhalb von Konvertern verwendet wurden: converter toInt(x: MyType): int = let global {.global.} = MyType() # Generierte ungültigen C-Code result = global.value
- Ein Compiler-Absturz wurde behoben, der bei der Generierung von Ausnahmen vom Typ Defect und der Verwendung von doAssert in bestimmten Kontexten auftrat.
- Verbesserungen im Typsystem
- Das Zurückgeben von lent-Werten aus case/if-Ausdrücken wurde korrigiert: proc getBest(a, b: string): lent string = if a.len > b.len: return a # Früher: Kompilierungsfehler else: return b
- Das Problem mit der fehlerhaften Speicherung von lent-Feldwerten in generischen Typen wurde behoben: type Wrapper[T] = object data: lent T proc process[T](w: Wrapper[T]) = echo w.data # Der Wert wird jetzt korrekt gespeichert.
- Die Überprüfung der Initialisierung der Variablen result für Typen mit requiresInit, die in Version 2.2 beschädigt wurde, wurde wiederhergestellt: type MustInit {.requiresInit.} = object value: int proc test(): MustInit = discard # Jetzt wird korrekt ein Fehler über das nicht initialisierte result ausgegeben.
- Das Ignorieren der Nicht-Kopierbarkeit (».noCopy«) des Basistyps wurde behoben: type Base {.noCopy.} = object Derived = object of Base var a: Derived var b = a # Jetzt ist es korrekt verboten.
- Leistungsoptimierungen.
- Beschleunigung des Operators «@» für triviale Typen: Kritische Leistungsverschlechterung beim Erstellen von Sequenzen aus Arrays einfacher Typen wurde behoben: let arr = [1, 2, 3, 4, 5] let s = @arr # Es war extrem langsam, jetzt optimal.
- Optimierung von vmgen.sameConstant: Die Kompilierung wurde durch die Optimierung des Vergleichs von Konstanten erheblich beschleunigt. virtuellen Maschine im Compiler und die Reduzierung von Speicherauslagerungen.
- Die Dereferenzierung des cast-Ergebnisses in einem einzelnen Ausdruck verursacht kein unnötiges Kopieren mehr: let data = cast[ptr MyType](address)[] # Jetzt ohne Kopieren
- Backend-spezifische Korrekturen
- JavaScript
- =destroy für nicht-var-Typen: die Generierung von Destruktoren wurde korrigiert, die zuvor zu Kompilierungsfehlern führte.
- cast[char] für Werte > 255: jetzt wird das Truncation korrekt ausgeführt, wie im C-Backend.
- Konzepte in varargs: die Ausgabe des Fehlers "internal error" bei der Übergabe von Konzepten in varargs wurde behoben.
- C++: L-Wertigkeit für kompatible Typen wiederhergestellt, die zwischen den Versionen 2.2.2 und 2.2.4 in einer Regression beschädigt wurde: # nim cpp var x: CppCompatibleType takeRef(x) # Funktioniert wieder als lvalue
- C (refc)
- pthread auf einigen Plattformen: die Code-Generierung für pthread_mutex_t unter Verwendung von .abi wurde korrigiert;
- Generische Typen mit GC-Speicher: die Generierung von inkorrektem C-Code für generische Typen, die verwalteten Speicher enthalten, wurde behoben;
- JavaScript
- Virtuelle Maschine
- Globale Variablen und Zuweisungen: mehrere Korrekturen für den Umgang mit globalen Variablen während der Kompilierung.
- Case-Objekte aus compileTime proc: die Übergabe von variant Objekten als static-Parameter wurde korrigiert.
- repr für lange Strings unter refc: RangeDefect bei Verwendung von repr wurde behoben.
- Änderungen in der Standardbibliothek
- In strutils.formatSize wurde die Verarbeitung großer Werte, die nahe an int64.high liegen, korrigiert: echo formatSize(9223372036854775807) # Jetzt korrektes Ergebnis
- In deques wurde die Kompatibilität des Verhaltens des Iterators items zwischen den Versionen 2.0.16 und 2.2.0 wiederhergestellt.
- In lists.SinglyLinkedList.remove wurde der AssertionDefekt beim Entfernen von Elementen aus der einfach verketteten Liste behoben.
- In tables.withValue wurde die Bedingung zur Überprüfung im withValue-Makro für unveränderliche Tabellen korrigiert.
- Pragmas und Sichtbarkeitsbereiche
- In «{.push raises: [].}» wurde die fehlerhafte Ignorierung lexikalischer Sichtbarkeiten für push-Pragmas mit raises korrigiert.
- Der Effekt der Warnung "Leck" nach dem Deaktivieren von Warnungen außerhalb der pragma-Blöcke wurde behoben: {.push warning[UnusedImport]: off.} import module1 {.pop.} import module2 # Warnungen sind jetzt korrekt aktiviert
- Weitere wichtige Korrekturen
- Vergleich cstring: Die fehlenden Operatoren «<» und «cmp» für cstring wurden hinzugefügt.
- Überprüfung der float-Bereiche: Eine korrekte Überprüfung der Bereiche für Fließkommazahlen wurde implementiert.
- filterIt und rvalue: Die fehlerhafte Rückgabe von rvalue anstelle von lvalue wurde behoben.
- Ein FieldDefect wurde beim Vergleich von Zeigern während der Kompilierung behoben.
- hasCustomPragma nach dem Kopieren des typedesc: die Funktionalität nach dem Kopieren der Typ-Deskriptoren wurde wiederhergestellt.
- nim doc und private Felder: Verwendung von Kommentaren für öffentliche Zugriffe auf private Felder wurde korrigiert.
Quelle: opennet.ru
