Rilascio del linguaggio di programmazione Nim 2.2.6

È stato rilasciato il linguaggio di programmazione di sistema Nim 2.2.6. L'aggiornamento è disponibile sei mesi dopo il rilascio della versione 2.2.4 e include 141 commit con correzioni di bug e miglioramenti delle prestazioni. Nim è un linguaggio di programmazione compilato, staticamente tipizzato, con una sintassi ispirata a Python e capacità di metaprogrammazione simili a Lisp. Il linguaggio viene compilato in C, C++ e JavaScript, garantendo prestazioni simili a quelle del C, con l'espressività dei linguaggi di alto livello. Il codice del progetto è distribuito sotto licenza MIT.

Le caratteristiche principali di Nim includono un potente sistema di macro che opera sull'AST durante la compilazione, un avanzato sistema di programmazione generica con concetti, dispatching multiplo (multiple dispatch), gestione della memoria deterministica con supporto per diverse strategie (ARC/ORC, refc, marcatura-e-raccolta), supporto integrato per async/await per la programmazione asincrona e FFI per una facile integrazione con C/C++/JavaScript. Nim si posiziona come linguaggio di sistema, adatto allo sviluppo da sistemi embedded a applicazioni web.server, con un focus su efficienza, sicurezza della memoria e facilità di sviluppo.

Principali modifiche:

  • Ottimizzazione della semantica move per i campi degli oggetti. Il compilatore ha imparato a riconoscere la possibilità di utilizzare operazioni move al ritorno dei campi degli oggetti. In precedenza, costrutti come «return obj.field» portavano alla copia dei dati, ora il compilatore applica correttamente lo spostamento: proc getField(obj: MyObject): string = return obj.field # Ora move invece di copy

    Questo è particolarmente importante per i tipi di dati pesanti (stringhe, sequenze, oggetti con risorse), dove l'eliminazione di copie superflue offre un notevole guadagno in termini di prestazioni senza dover modificare il codice.

  • Riprogettazione completa degli iteratori closure con gestione delle eccezioni. Il meccanismo di trasformazione degli iteratori closure è stato completamente riscritto, migliorando drasticamente la stabilità del codice async con la gestione delle eccezioni. Risolti problemi critici, inclusi SIGSEGV durante l'uso di try/except non al livello superiore: iterator problematicIterator(): int {.closure.} = for i in 0..10: try: if i == 5: raise newException(ValueError, «test») yield i except ValueError: discard # In precedenza causava SIGSEGV

    È stata inoltre risolta la questione del passaggio errato delle eccezioni nei blocchi finally all'interno degli iteratori closure.

  • Correzioni relative alla gestione della memoria
    • Risolto un problema fondamentale nel garbage collector durante la gestione delle strutture dati cicliche, che poteva portare a un errore "Accesso alla memoria non valido". Questo problema esisteva sin dalla creazione del linguaggio e si manifestava con grafi complessi di oggetti con riferimenti reciproci.
    • Corretto l'ordine errato di distruzione degli oggetti, che poteva portare a riferimenti a memoria già liberata: type Resource = object data: ptr Data Container = object resource: Resource other: OtherResource # Ora i distruttori vengono chiamati nel corretto ordine: # prima other, poi resource
    • Il garbage collector ORC etichettava erroneamente alcuni ambienti di chiusura come ciclici, causando ritardi nel rilascio della memoria o perdite. Ora l'analisi dei cicli funziona correttamente.
    • Corretta una perdita di socket in asyncnet durante errori di negoziazione di connessione TLS: proc handleClient() {.async.} = var socket = await server.accept() try: await socket.setupSSL() # In caso di errore, qui socket viene ora chiuso correttamente except SSLError: discard # Il socket non perde più
  • Correzioni critiche nel compilatore.
    • È stata risolta una regressione in cui le variabili globali dichiarate all'interno di procedure con parametri statici venivano reinizializzate ad ogni chiamata: proc test[N: static int]() = var global {.global.}: array[N, int] global[0] += 1 echo global[0] test[5]() # Output: 1 test[5]() # Dovrebbe: 2, ma output: 1 (riinizializzato)
    • Corretto la generazione del codice per le variabili globali nelle funzioni ricorsive, che portava a comportamenti imprevisti.
    • Risolto un antico problema nella generazione di codice C non valido quando si usano costruttori per le variabili globali all'interno di convertitori: converter toInt(x: MyType): int = let global {.global.} = MyType() # Generava codice C non valido result = global.value
    • Eliminato il crash del compilatore durante la generazione di eccezioni di tipo Defect e l'uso di doAssert in determinati contesti.
  • Miglioramenti nel sistema di tipi
    • Corretto il problema di impossibilità di restituire valori lent da espressioni case/if: proc getBest(a, b: string): lent string = if a.len > b.len: return a # In precedenza: errore di compilazione else: return b
    • Risolto il problema di salvataggio errato dei valori dei campi lent nei tipi generici: type Wrapper[T] = object data: lent T proc process[T](w: Wrapper[T]) = echo w.data # Il valore ora viene salvato correttamente
    • Ripristinato il controllo di inizializzazione per la variabile result per tipi con requiresInit, che era rotto nella versione 2.2: type MustInit {.requiresInit.} = object value: int proc test(): MustInit = discard # Ora genera correttamente un errore su result non inizializzato
    • Corretto il problema dell'ignoranza della non copiabilità («.noCopy») del tipo base: type Base {.noCopy.} = object Derived = object of Base var a: Derived var b = a # Ora è correttamente vietato
  • Ottimizzazioni delle prestazioni
    • Accelerazione dell'operatore «@» per tipi banali: risolta una grave degradazione delle prestazioni nella creazione di sequenze da array di tipi semplici: let arr = [1, 2, 3, 4, 5] let s = @arr # Era estremamente lento, ora è ottimale
    • Ottimizzazione vmgen.sameConstant: compilazione significativamente accelerata grazie all'ottimizzazione del confronto delle costanti in macchina virtuale compilatore e riduzione delle operazioni di allocazione della memoria.
    • La dereferenziazione del risultato del cast in un'espressione singola non provoca più copie inutili: let data = cast[ptr MyType](address)[] # Ora senza copie
  • Correzioni specifiche del backend
    • JavaScript
      • =destroy per tipi non-var: corretta la generazione dei distruttori, che in precedenza portava a errori di compilazione.
      • cast[char] per valori > 255: ora il troncamento viene eseguito correttamente, come nel backend C.
      • Concetti in varargs: eliminato l'output dell'errore «internal error» durante il passaggio di concetti in varargs.
    • C++: Ripristinato il valore L per tipi compatibili che era stato interrotto in una regressione tra le versioni 2.2.2 e 2.2.4: # nim cpp var x: CppCompatibleType takeRef(x) # Funziona di nuovo come lvalue
    • C (refc)
      • pthread su alcune piattaforme: corretta la generazione del codice per pthread_mutex_t utilizzando .abi;
      • Tipi generici con memoria GC: eliminata la generazione di codice C non corretto per i tipi generici contenenti memoria gestita;
  • Macchina virtuale
    • Variabili globali e assegnazioni: molteplici correzioni nella gestione delle variabili globali durante la compilazione.
    • Oggetti case da proc compileTime: corretta la trasmissione di oggetti varianti come parametri statici.
    • repr per stringhe lunghe sotto refc: eliminato RangeDefect durante l'uso di repr.
  • Correzioni nella libreria standard
    • In strutils.formatSize è stata corretta la gestione dei valori grandi, vicini a int64.high: echo formatSize(9223372036854775807) # Ora restituisce il risultato corretto
    • Nella deques è stata ripristinata la compatibilità del comportamento dell'iteratore items tra le versioni 2.0.16 e 2.2.0.
    • In lists.SinglyLinkedList.remove è stato risolto un AssertionDefect durante la rimozione di elementi dalla lista collegata semplice.
    • In tables.withValue è stata corretta la condizione di verifica nel macro withValue per le tabelle immutabili.
  • Pragmi e aree di visibilità
    • In «{.push raises: [].}» è stata corretta l'erronea ignoranza delle aree di visibilità lessicale per le pragmi push con raises.
    • È stato eliminato l'effetto di "perdita" della disattivazione degli avvisi al di fuori dei blocchi pragma: {.push warning[UnusedImport]: off.} import module1 {.pop.} import module2 # Gli avvisi ora vengono riattivati correttamente
  • Altre correzioni importanti
    • Confronto cstring: aggiunti gli operatori mancanti «<» e «cmp» per cstring.
    • Controllo dei range float: è stato abilitato il controllo corretto dei range per i numeri a punto flottante.
    • filterIt e rvalue: è stata corretta la restituzione errata di rvalue invece di lvalue.
    • Eliminato FieldDefect nel confronto dei puntatori durante la fase di compilazione.
    • hasCustomPragma dopo la copia typedesc: ripristinata la funzionalità dopo la copia dei descrittori di tipo.
    • nim doc e campi privati: corretto l'uso dei commenti dai campi privati per quelli pubblici.

Fonte: opennet.ru

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster