Byl vydán systémový programovací jazyk Nim 2.2.6. Tato aktualizace přichází šest měsíců po vydání verze 2.2.4 a obsahuje 141 commitů s opravami chyb a vylepšeními výkonu. Nim je staticky typovaný, kompilovaný programovací jazyk se syntaxí inspirovanou Pythonem a metaprogramovacími možnostmi podobnými jazyku Lisp. Kompiluje se do jazyků C, C++ a JavaScript, a poskytuje výkon na úrovni C s expresivitou vyšších jazyků. Kód projektu je licencován pod licencí MIT.
Mezi klíčové vlastnosti jazyka Nim patří výkonný systém maker, který pracuje na AST v době kompilace, bohatý systém generického programování s koncepty, vícenásobné odesílání, deterministická správa paměti s podporou více strategií (ARC/ORC, refc, mark-and-sweep), vestavěná podpora asynchronního programování (async/await) a FFI pro snadnou integraci s C/C++/JavaScript. Nim je pozicionován jako systémový jazyk vhodný pro vývoj od vestavěných systémů až po webové aplikace.servery, s důrazem na efektivitu, bezpečnost paměti a pohodlí vývojářů.
Klíčové změny:
- Optimalizace sémantiky přesunu pro objektová pole. Kompilátor se naučil rozpoznávat možnost použití operací přesunu při vracení objektových polí. Dříve konstrukce jako "return obj.field" vedly ke kopírování dat; nyní kompilátor správně aplikuje přesun: proc getField(obj: MyObject): string = return obj.field # Nyní použijte přesun místo kopírování
To je obzvláště důležité pro datové typy s velkým objemem dat (řetězce, sekvence, objekty se zdroji), kde eliminace zbytečného kopírování poskytuje znatelné zvýšení výkonu bez změny kódu.
- Kompletní přepsání iterátorů uzavírání s ošetřením výjimek. Mechanismus pro transformaci iterátorů uzavírání byl kompletně přepsán, což dramaticky zlepšuje stabilitu asynchronního kódu s ošetřením výjimek. Byly opraveny kritické problémy, včetně SIGSEGV při použití try/except na jiné než nejvyšší úrovni: iterator problematicIterator(): int {.closure.} = for i in 0..10: try: if i == 5: raise newException(ValueError, "test") yield i except ValueError: discard # Dříve způsobená chyba SIGSEGV
Problém s nesprávným šířením výjimek v blocích finally uvnitř iterátorů uzávěrů byl také vyřešen.
- Opravy související se správou paměti
- Byl opraven zásadní problém ve zpracování cyklických datových struktur garbage collectorem. Tento problém mohl vést k chybě „Neplatný přístup k úložišti“. Tento problém existoval od vzniku jazyka a projevoval se ve složitých grafech objektů se vzájemnými odkazy.
- Opraveno nesprávné pořadí ničení objektů, které mohlo vést k přístupu k již uvolněné paměti: type Resource = object data: ptr Data Container = object resource: Resource other: OtherResource # Nyní se destruktory volají ve správném pořadí: # nejprve other, pak resource
- Kompilátor ORC nesprávně označil některá prostředí uzavírání jako cyklická, což vedlo ke zpožděním uvolňování paměti nebo únikům. Analýza cyklů nyní funguje správně.
- Opravena chyba úniku socketu v asyncnet při chybách vyjednávání TLS připojení: proc handleClient() {.async.} = var socket = await server.accept() try: await socket.setupSSL() # Při chybě je socket nyní správně uzavřen, s výjimkou SSLError: discard # Socket již neuniká
- Kritické opravy v kompilátoru.
- Opravena regrese, kdy globální proměnné deklarované uvnitř procedur se statickými parametry byly při každém volání znovu inicializovány: proc test[N: static int]() = var global {.global.}: array[N, int] global[0] += 1 echo global[0] test[5]() # Výstup: 1 test[5]() # Mělo být výstup: 2, ale výstup: 1 (bylo znovu inicializováno)
- Opraveno generování kódu pro globální proměnné v rekurzivních funkcích, které způsobovalo nedefinované chování.
- Opraven starý problém s generováním neplatného kódu C při použití konstruktorů pro globální proměnné uvnitř převodníků: converter toInt(x: MyType): int = let global {.global.} = MyType() # Vygenerovaný neplatný kód C result = global.value
- Opraven pád kompilátoru při vyvolání výjimek Defect a použití doAssert v určitých kontextech.
- Vylepšení systému typů
- Opravena nemožnost vracet hodnoty typu lent z výrazů case/if: proc getBest(a, b: string): lent string = if a.len > b.len: return a # Dříve: chyba kompilace else: return b
- Opraven problém s nesprávným ukládáním hodnot polí typu lent v generických typech: type Wrapper[T] = object data: lent T proc process[T](w: Wrapper[T]) = echo w.data # Hodnota je nyní uložena správně
- Obnovena kontrola inicializace proměnné výsledku pro typy s requiresInit, která byla ve verzi 2.2 nefunkční: type MustInit {.requiresInit.} = object value: int proc test(): MustInit = discard # Nyní správně vyvolá chybu o neinicializovaném výsledku
- Opraveno ignorování nekopírovatelnosti (".noCopy") základního typu: type Base {.noCopy.} = object Derived = object of Base var a: Derived var b = a # Nyní správně zakázáno
- Optimalizace výkonu
- Zrychlení operátoru "@" pro triviální typy: bylo eliminováno kritické snížení výkonu při vytváření sekvencí z polí jednoduchých typů: let arr = [1, 2, 3, 4, 5] let s = @arr # Bylo extrémně pomalé, nyní optimální
- Optimalizace vmgen.sameConstant: kompilace byla výrazně zrychlena optimalizací porovnávání konstant v virtuální stroj kompilátor a redukce operací alokace paměti.
- Dereferencování výsledku přetypování v jednom výrazu již nezpůsobuje zbytečné kopírování: let data = cast[ptr MyType](address)[] # Nyní bez kopírování
- Opravy specifické pro backend
- JavaScript
- =destroy pro typy jiné než var: Opraveno generování destruktorů, které dříve způsobovalo chyby při kompilaci.
- cast[char] pro hodnoty > 255: nyní správně provádí zkrácení, stejně jako v C-backendu.
- Koncepty v proměnných: Opravena chyba „interní chyba“ při předávání konceptů v proměnných.
- C++: Obnovena l-hodnota kompatibilních typů, která byla porušena v regresi mezi verzemi 2.2.2 a 2.2.4: # nim cpp var x: CppCompatibleType takeRef(x) # Funguje opět jako lhodnota
- C (ref.)
- pthread na některých platformách: opraveno generování kódu pro pthread_mutex_t pomocí .abi;
- Generiky s GC pamětí: Opraveno generování nesprávného kódu C pro generické typy obsahující spravovanou paměť;
- JavaScript
- Virtuální stroj
- Globální proměnné a přiřazení: Několik oprav zpracování globálních proměnných během kompilace.
- Objekty Case z procedury compileTime: Opraveno předávání objektů Case jako statických parametrů.
- repr pro dlouhé řetězce pod refc: Opravena chyba RangeDefect při použití repr.
- Opravy ve standardní knihovně
- Ve strutils.formatSize byla opravena práce s velkými hodnotami blízkými int64.high: echo formatSize(9223372036854775807) # Nyní je výsledek správný
- V deques bylo chování iterátoru položek obnoveno tak, aby bylo kompatibilní mezi verzemi 2.0.16 a 2.2.0.
- V souboru lists.SinglyLinkedList.remove byla opravena chyba AssertionDefect, která se vyskytovala při odebírání prvků z jednotlivě propojeného seznamu.
- V souboru tables.withValue byla opravena kontrolní podmínka v makru withValue pro neměnné tabulky.
- Pragmata a rozsahy
- Opraveno nesprávné ignorování lexikálních oborů pro push pragmata s navýšením v "{.push raises: [].}".
- Opraven efekt „úniku“ při deaktivaci varování mimo bloky pragma: {.push warning[UnusedImport]: off.} import module1 {.pop.} import module2 # Varování jsou nyní správně povolena
- Další důležité opravy
- Porovnání cstringů: přidány chybějící operátory "<" a "cmp" pro cstring.
- Kontrola rozsahu čísel s plovoucí desetinnou čárkou: Je povolena správná kontrola rozsahu čísel s plovoucí desetinnou čárkou.
- filterIt a rvalue: Opraveno chybné vrácení rvalue místo lvalue
- Opraven FieldDefect při porovnávání ukazatelů během kompilace.
- hasCustomPragma po zkopírování typedesc: funkčnost obnovena po zkopírování deskriptorů typů.
- dokumentace NIM a soukromá pole: opraveno používání komentářů ze soukromých polí pro veřejná.
Zdroj: opennet.ru
