Sipeligrarimi i parimeve të dizajnit të kompajlerit Nimony për versionin e ardhshëm Nim 3.0

Gjatë zhvillimit të gjuhës së programimit Nim 3.0 po zhvillohet një kompilator i ri Nimony, i cili ka si parim themelor të dizajnit arritjen e parashikueshmërisë së kohës së ekzekutimit në rastin më të keq (Worst Case Execution Time, WCET). Kjo kërkesë është e diktuar nga orientimi drejt sistemeve të kohës reale të ngurtë, ku sjellja e padeterminueshme nuk lejohet. Si rezultat, arkitektura Nimony përjashton përdorimin e kompilatorëve JIT dhe mbledhësve të plehrave me gjurmim (tracing garbage collectors), pasi operacionet e tyre mund të sjellin vonesa të paparashikueshme.

Për të arritur parashikueshmërinë, tipet primare të dhënave (numra të plotë, karaktere) shfaqen drejtpërdrejt në fjalë makine dhe byte të arkitekturës përkatëse. Tipet kompozite (strukturat, objektet) formohen pa përdorimin e adresimit të tërthortë (indirection), duke u vendosur direkt në stack ose brenda strukturave të tjera të dhënash. Ky qasje minimizon shpenzimet dhe siguron një përputhje më të qartë midis kodit burimor dhe kodit të gjeneruar të makinës.

Në fushën e menaxhimit automatik të memories (MM), Nimony tërheq përparësi nga diversiteti i opsioneve në Nim 2.0, duke ofruar një mod të standardizuar: «mm:atomicArc». Ky mod bazohet në numërimin e referencave duke përdorur operacione atomike, për të cilat është e shtuar semantika e zhvendosjes (move semantics) dhe thirrja e destruktoreve gjatë shkatërrimit të objektit, duke e afruar qasjen me praktikat e pranuara në Rust dhe C++ moderne.

Një risitë kyçe është ndarja e qartë e objekteve në aciklike dhe potencialisht ciklike. Sipas parazgjedhjes, objektet konsiderohen aciklike (.acyclic), që është një sjellje e re. Për llojet e të dhënave, instancat e të cilave mund të formojnë lidhje ciklike, kërkohet një annotim i qartë me pragmën .cyclic. Vihet në dukje se po zhvillohet një algoritëm i ri për mbledhjen e lidhjeve ciklike, megjithatë gatishmëria e tij për përdorim industrial aktualisht nuk garantohet. Avantazhi i MM për bazë të destruktoreve është kompozueshmëria e tij: menaxhimi i burimeve që kërkojnë çlirimin (p.sh., deshifruesit e skedarëve, socketet rrjetit, kanalet), integrohet natyrshëm përmes destruktoreve të llojeve përkatëse.

Qasja në përpunimin e gabimeve në Nimony ka pësuar ndryshime të mëdha. Autori Nim shpreh pakënaqësinë e tij me mekanizmat tradicionalë të përjashtimeve dhe emulimin e tyre përmes llojeve algebrike të të dhënave (llojet e përmbledhura). Në vend të kësaj, propozohet koncepti i integrimit të gjendjes së gabimit direkt në vetë objektin e të dhënave. Si shembuj, përmenden: përfaqësimi i gabimit në rrjedhat e hyrjeve-daljeve përmes një gjendjeje të veçantë, përdorimi i NaN për numrat me pikë të flotueshme, ose low(int) për vlera të pavlefshme të numrave të plotë. Në rastet kur objekti nuk mund të inkorporojë gjendjen e gabimit, rekomandohet përdorimi i një variabli të lokalizuar në thread për sinjalizim.

Megjithatë, mekanizmi tradicional i përjashtimeve në Nim mbetet, por me një sqarim të rëndësishëm: çdo procedurë që ka potencialin të prodhojë një përjashtim tani duhet të annotohet domosdoshmërisht me pragmën {.raises.}. Kjo kërkesë synon të shënojë qartë kalimet e mundshme jolonale të menaxhimit.

Si alternativë ose plotësuese, është prezantuar një tip i ri enumerativ ErrorCode. Ky tip është i sigurt për lloje dhe kërkon trajtim të plotë të të gjitha mundësive (përkatësisht siç bëhet me case për enum). ErrorCode është projektuar duke marrë parasysh mundësinë e shfaqjes në kodet standard të gabimeve të sistemeve dhe protokolleve të ndryshme, si errno POSIX, kodet e gabimeve të API Windows dhe statuset HTTP. Qëllimi është unifikimi i trajtimit të gabimeve midis bibliotekave të ndryshme dhe të mundësojë transmetimin e drejtpërdrejtë të gabimeve sistemore (p.sh., "disku është i mbushur") në kodet përkatëse të statusit (p.sh., HTTP 507) pa konvertime të tjera. Përdorimi i ErrorCode gjithashtu lejon trajtimin dhe shpërndarjen e gabimeve pa alokimin e memories në heap, që është kritik për trajtimin e situatave të mungesës së memories (OOM).

Trajtimi i situatave të shkarkimit të memories (Out of Memory, OOM) në Nimony është realizuar duke u larguar nga praktika e zakonshme e përfundimit të papritur të programit ("die on OOM"). Në vend të kësaj, ofrohet një mekanizëm që lejon aplikacionin të vazhdojë punën. Kontejnerët dhe operacionet e alokimit të memories që nuk mund të përmbushin kërkesën, thërrasin një trajtues të ri të përcaktueshëm oomHandler. Zbatimi i parazgjedhur regjistron madhësinë e kërkesës së dështuar në një variabël të lokalizuar në thread dhe lejon që ekzekutimi të vazhdojë. Gjendja e mungesës së memories për thread-in aktual mund të kontrollohet me thirrjen threadOutOfMem().

Zhvilluesi mund të sigurojë një implementim të tij për oomHandler, për shembull, për regjistrimin apo për ndërprerjen e aplikacionit në rast se një sjellje e tillë është e preferuar. Një aspekt i rëndësishëm është trajtimi i operacioneve të ndërtimit të objekteve referuese (ref object), të cilat mund të dështojnë për shkak të OOM. Në Nimony, rezultati i këtyre operacioneve (për shembull, nëpërmjet new ose ndërtuesve të ngjashëm) mund të jetë nil, dhe kompajleri e detyron trajtimin e këtij rasti në mënyrë të ngjashme me punimin me llojet opsionale (Option), duke parandaluar kështu gabimet e dereferencës së treguesit null. Në kontekstin e procedurave të anotuar me {.raises.}, vlera e kthyer nil mund të konvertohet automatikisht në ErrorCode.OutOfMemError.

Mekanizmi i programimit të përgjithshëm (generics) në Nimony ka zhvilluar më shumë se sa në Nim 2.0. Përmirësimi kryesor qëndron në faktin se kontrolli i plotë i tipave të kodit të përgjithshëm tani kryhet në fazën e përcaktimit të tij, dhe jo vetëm kur instancohet me tipe specifike. Pritet që kjo të lejojë identifikimin e gabimeve në faza më të herëshme të kompilimit, të ofrojë mesazhe më informuese për gabimet dhe të përmirësojë mbështetjen nga mjetet e zhvillimit (IDE), veçanërisht autocompletion-in e kodit.

Konceptele (concepts) që tashmë janë të pranishme në Nim mbajnë rolin e tyre si mekanizëm i përshkrimit statik të kërkesave për tipet parametrike të funksioneve dhe tipeve të përgjithshme. Ato lejojnë që në mënyrë formale të spesifikohet se cilave operacione ose pronësi duhet t'i përkojë një tip për t'u përdorur në këtë kontekst të përgjithshëm.

Nimony synon të unifikohet modelet e programimit asinkron dhe shumëfishtë nën një konstruksion të vetëm, spawn. Vendimi nëse një detyrë, e nisur përmes spawn, do të ekzekutohet në të njëjtën kalim (asinkron) apo në një kalim të veçantë nga pool-i (shumëfishtë), merret nga planifikuesi gjatë ekzekutimit (runtime). Kjo vendos kërkesa të caktuara për argumentet që dërgohen në spawn: ato duhet të jenë të sigurta për kalimet e shumëfishta.

Implementimi i brendshëm i modelit të konkurrencës do të bazohet në vazhdimësitë (continuations), dhe kompileri do të bëjë transformimin e programit në stilin e kalimit të vazhdimësive (Continuation-Passing Style, CPS). Vërehet se konstrukti spawn nuk është realizuar si një mundësi e integruar e gjuhës, por si një plugin i kompilerit.

Paralelizmi konsiderohet një detyrë më e thjeshtë krahasuar me konkurrencën. Për të shkruar kod krejtësisht paralel, të orientuar ndaj llogaritjeve (për shembull, përpunimi i grupeve të dhënash), Nimony do të ofrojë struktura speciale, siç janë ciklet paralel for, të shënuara me operatorin «||». Kjo do të lejojë implementimin e algoritmeve paralel pa pasur nevojë për përdorimin e variablave të rrjedhës (flow vars), që mund të jetë e dobishme për detyra shkencore ose programim për GPU.

Sistemi i metaprogramimit të Nim, i njohur për makros, në Nimony evoluon drejt shtesave të kompilatorit (compiler plugins). Shtesat janë kod që kompilohen në instruksione natyrore dhe ekzekutohen në faza të vona të punës së kompilatorit, pas fazës së verifikimit të tipeve. Kjo i jep shtesave qasje në të gjitha informacionet rreth tipeve dhe semantikës së kodit që po analizohet.

Janë premtuar API më të avancuara dhe më të lehta për zhvillimin e shtesave. Përdorimi i formatit ndërmjetës NIF (Nim Intermediate Format) gjithashtu do ta bëjë më të lehtë implementimin e transformimeve të ndryshme të kodit. Shtesat mund të ekzekutohen në mënyrë inkrementale dhe paralelisht, çka ndihmon në rritjen e produktivitetit të kompilimit.

Llojet e shtesave:

  • Shtesa pĂ«r shabllone (Template Plugins): RrĂ«shqasin nĂ« shabllone tĂ« caktuara dhe pĂ«rpunojnĂ« kodin e lidhur me thirrjet e tyre.
  • Shtesat modulare (Module Plugins): Marrin nĂ« input AST (Abstract Syntax Tree) tĂ« modulit tĂ« tĂ«rĂ« dhe duhet tĂ« kthejnĂ« pemĂ«n e transformuar. Konstrukti spawn Ă«shtĂ« njĂ« shembull i implementimit pĂ«rmes njĂ« shtese moduli.
  • Shtesat pĂ«r iteratorĂ«t: TĂ« ngjashme me shtesat pĂ«r shabllone, por pĂ«rdoren te iteratorĂ«t.
  • Shtesat pĂ«r tipet nominale: Mund tĂ« lidhen me lloje tĂ« caktuara tĂ« tĂ« dhĂ«nave, duke zĂ«vendĂ«suar mekanizmin "makros pĂ«rshkruese" (term rewriting macros) nga Nim. Kjo lejon realizimin e optimizimeve, siç Ă«shtĂ« eliminimi i objekteve tĂ« pĂ«rkohshme gjatĂ« ekzekutimit tĂ« operacioneve matricore.

Për dokumentacionin Nimony është parashikuar një faqe, e gjeneruar plotësisht nga AI dhe e verifikuar nga autori i Nim për saktësinë.

Burimi: opennet.ru

Bli njĂ« hosting tĂ« besueshĂ«m pĂ«r faqet me mbrojtje DDoS, VPS VDS serverĂ« đŸ”„ Bli njĂ« hosting tĂ« besueshĂ«m pĂ«r faqet me mbrojtje DDoS, VPS VDS serverĂ« | ProHoster