Përpiluesi

Në informatikë, një **kompilues** është një program që përkthen kodin kompjuterik të shkruar në një gjuhë programimi (gjuha *burimore* ) në një gjuhë tjetër (gjuha *e synuar* ). Emri "kompilues" përdoret kryesisht për programet që përkthejnë kodin burimor nga një gjuhë programimi e nivelit të lartë në një gjuhë programimi të nivelit të ulët (p.sh. gjuha e asamblesë, kodi i objektit ose kodi i makinës ) për të krijuar një program të ekzekutueshëm .   

Ekzistojnë shumë lloje të ndryshme kompilatorësh që prodhojnë rezultate në forma të ndryshme të dobishme. Një  *kompiluesi i kryqëzuar* prodhon kod për një CPU ose sistem operativ të ndryshëm nga ai në të cilin funksionon vetë ai. Një *kompilues vetëndërtues* është shpesh një kompilues i përkohshëm, i përdorur për kompilimin e një kompiluesi më të përhershëm ose më të optimizuar për një gjuhë.

Softuerët e lidhur përfshijnë *dekompilues*, programe që përkthejnë nga gjuhët e nivelit të ulët në ato të nivelit më të lartë; programe që përkthejnë midis gjuhëve të nivelit të lartë, zakonisht të quajtura *kompilues burim-në-burim* ose *transpilues* ; *rishkruesit* e gjuhëve, zakonisht programe që përkthejnë formën e shprehjeve pa ndryshim të gjuhës; dhe *kompiluesit-kompilues*, kompilues që prodhojnë kompilues (ose pjesë të tyre), shpesh në një mënyrë gjenerike dhe të ripërdorshme në mënyrë që të jenë në gjendje të prodhojnë më shumë kompilues të ndryshëm.

Një kompilues ka të ngjarë të kryejë disa ose të gjitha operacionet e mëposhtme, të cilat shpesh quhen faza: parapërpunim, analizë leksikore, analizim, analizë semantike ( përkthim i drejtuar nga sintaksa ), konvertim i programeve hyrëse në një përfaqësim të ndërmjetëm, optimizim i kodit dhe gjenerim i kodit specifik të makinës . Kompiluesit në përgjithësi i zbatojnë këto faza si komponentë modularë, duke promovuar projektimin efikas dhe korrektësinë e transformimeve të hyrjes burimore në daljen e synuar. Gabimet e programit të shkaktuara nga sjellja e gabuar e kompiluesit mund të jenë shumë të vështira për t'u gjetur dhe për t'u përpunuar; prandaj, zbatuesit e kompiluesve investojnë përpjekje të konsiderueshme për të siguruar saktësinë e kompiluesit . 

## Krahasimi me interpretuesin (përkthyesin) 
Në lidhje me krijimin e kodit burimor që mund të ekzekutohet, një interpretues kryen një funksion të ngjashëm me kompiluesin, por përdor një mekanizëm tjetër. Ai ekzekuton kodin pa e kthyer drejtpërdrejt në kod makine. Disa interpretues ekzekutojnë direkt kodin burimor, ndërsa të tjerë e përpunojnë një formë të ndërmjetme, si bytecode.

Prandaj, një program i kompiluar në kodin nativ tenton të funksionojë më shpejt sesa kur interpretohet. Mjediset që përdorin një format ndërmjetësues bytecode kanë zakonisht një shpejtësi të ndërmjetme. Ndërsa kompilimi në kohë reale mundëson shpejtësi ekzekutimi të ngjashme me kodin natyror, duke pasur vetëm një kosto fillestare të përpunimit gjatë nisjes..

Për gjuhët e programimit të nivelit të ulët, siç janë assembly dhe C, është tipike që ato të kompilohen, veçanërisht kur shpejtësia është një shqetësim i rëndësishëm, dhe jo të mbështeten si platforma të ndryshme. Për këto gjuhë, ekzistojnë më shumë përputhje një-në-një midis kodit burimor dhe kodit të makinës që rezulton, duke e bërë më të lehtë për programuesit të kontrollojnë përdorimin e pajisjeve.

Në teori, një gjuhë programimi mund të përdoret nëpërmjet një kompiluesi ose një interpretuesi, por në praktikë, secila gjuhë tenton të përdoret vetëm me njërën ose tjetrën. Megjithatë, është e mundur të shkruhet një kompilues për një gjuhë që interpretohet zakonisht. Për shembull, Common Lisp mund të kompilohet në kod bajtesh Java (dhe pastaj të interpretohet nga makina virtuale Java ), si dhe në kodin C (pastaj të kompilohet në kodin vendas të makinës), ose direkt në kodin vendas.
parapamje|Një diagramë i funksionimit të një kompiluesit tipik shumëgjuhësh dhe shumë-objektivësh
Konceptet teorike të informatikës të zhvilluara nga shkencëtarë, matematikanë dhe inxhinierë formuan bazën e zhvillimit të informatikës dixhitale moderne gjatë Luftës së Dytë Botërore. Gjuhët binare primitive evoluan sepse pajisjet dixhitale kuptojnë vetëm njëshat dhe zerot dhe modelet e qarkut në arkitekturën themelore të makinës. Në fund të viteve 1940, gjuhët e asamblesë u krijuan për të ofruar një abstraksion më të realizueshëm të arkitekturave kompjuterike.  Kapaciteti i kufizuar i kujtesës së kompjuterëve të hershëm çoi në sfida të konsiderueshme teknike kur u projektuan kompiluesit e parë. Prandaj, procesi i kompilimit duhej të ndahej në disa programe të vogla. Programet e front-end prodhojnë rezultatet e analizës që përdoren nga programet e back-end për të gjeneruar kodin e synuar. Me përparimin e teknologjisë kompjuterike dhe ofrimin e më shumë burimeve, dizajnet e kompiluesve mund të përshtateshin më mirë me procesin e kompilimit.

Zakonisht është më produktive për një programues të përdorë një gjuhë të nivelit të lartë, kështu që zhvillimi i gjuhëve të nivelit të lartë pasoi natyrshëm nga aftësitë e ofruara nga kompjuterët dixhitalë. Gjuhët e nivelit të lartë janë gjuhë formale që përcaktohen në mënyrë strikte nga sintaksa dhe semantika e tyre të cilat formojnë arkitekturën e gjuhës së nivelit të lartë. Elementet e këtyre gjuhëve formale përfshijnë:

* Alfabeti, çdo grup i kufizuar simbolesh;
* Vargu, një sekuencë e kufizuar simbolesh;
* Gjuha, çdo grup vargjesh mbi një alfabet.

Fjalitë në një gjuhë mund të përcaktohen nga një sërë rregullash të quajtura gramatikë. 

Forma Backus-Naur (BNF) përshkruan sintaksën e "fjalive" të një gjuhe. U zhvillua nga John Backus dhe u përdor për sintaksën e Algol 60.  Idetë rrjedhin nga konceptet gramatikore pa kontekst nga gjuhëtari Noam Chomsky .  "BNF dhe zgjerimet e saj janë bërë mjete standarde për të përshkruar sintaksën e shënimeve të programimit. Në shumë raste, pjesë të përpiluesve gjenerohen automatikisht nga një përshkrim i BNF." 

Midis viteve 1942 dhe 1945, Konrad Zuse projektoi gjuhën e parë (algoritmike) të programimit për kompjuterët e quajtur  ("Plani i llogaritjes"). Zuse parashikoi gjithashtu një  ("Pajisja e montimit të planit") që të përkthente automatikisht formulimin matematikor të një programi në një material të lexueshëm nga makina, film të gjurmuar me vrima.  Edhe pse asnjë implementim praktik nuk u bë deri në vitet 1970, kjo paraqiste koncepte që më vonë u panë në APL   gjuhë e krijuar nga Ken Iverson në fund të viteve 1950.  APL është një gjuhë për llogaritjet matematikore.

Midis viteve 1949 dhe 1951, Heinz Rutishauser propozoi Superplanin, një gjuhë të nivelit të lartë dhe përkthyes automatik.  Idetë e tij u përmirësuan më vonë nga Friedrich L. Bauer dhe Klaus Samelson . 

Dizajni i gjuhës së nivelit të lartë gjatë viteve formuese të informatikës dixhitale siguroi mjete të dobishme programimi për një sërë aplikimesh:

* FORTRAN (Përkthimi i Formulave) për aplikime inxhinierike dhe shkencore konsiderohet të jetë një nga gjuhët e para të nivelit të lartë të implementuara në të vërtetë dhe përpiluesi i parë optimizues.  &#x5B; '''' &#x5D;
* COBOL (Gjuha e Përbashkët e Orientuar drejt Biznesit) evoluoi nga A-0 dhe FLOW-MATIC për t'u bërë gjuha dominuese e nivelit të lartë për aplikacionet e biznesit. 
* LISP (Procesori i Listave) për llogaritjen simbolike. 

Teknologjia e kompiluesve u zhvillua nga nevoja për të kthyer në mënyrë të saktë një program burimor të nivelit të lartë në një program objektiv të nivelit të ulët për kompjuterin dixhital. Kompiluesi mund të shihet si një front-end që merret me analizën e kodit burimor dhe një back-end që përpunon këtë analizë për të prodhuar kodin objektiv. Optimizimet midis front-end dhe back-end mund të çojnë në kod objektiv më efikas.

Disa faza të hershme në zhvillimin e teknologjisë së kompiluesve:

* *Maj 1952* : Ekipi i Grace Hopper në Remington Rand shkroi kompiluesin për gjuhën e programimit A-0 (dhe shpiku termin *kompilues* për ta përshkruar atë),    megjithëse kompiluesi A-0 funksiononte më shumë si një ngarkues ose lidhës sesa nocioni modern i një kompiluesi të plotë.   
* *1952, para shtatorit* : Një kompilues Autocode i zhvilluar nga Alick Glennie për kompjuterin Manchester Mark I në Universitetin e Mançesterit konsiderohet nga disa si gjuha e parë e programimit e kompiluar. 
* *1954–1957* : Një ekip i udhëhequr nga John Backus në IBM zhvilloi FORTRAN, i cili zakonisht konsiderohet si gjuha e parë e nivelit të lartë. Në vitin 1957, ata përfunduan një kompilues FORTRAN, i cili përgjithësisht njihet si ai që prezantoi kompiluesin e parë të plotë dhe të qartë. 
* *1959* : Konferenca mbi Gjuhën e Sistemeve të të Dhënave (CODASYL) nisi zhvillimin e COBOL . Dizajni i COBOL u mbështet në A-0 dhe FLOW-MATIC. Në fillim të viteve 1960, COBOL u kompilua në arkitektura të shumta.
* *1958–1960* : Algol 58 ishte pararendësi i ALGOL 60. Ai prezantoi blloqe kodi, një përparim kyç në rritjen e programimit të strukturuar . ALGOL 60 ishte gjuha e parë që zbatoi përkufizime të funksioneve të ndërthurura me fushëveprim leksikor . Ai përfshinte rekursionin . Sintaksa e tij u përcaktua duke përdorur BNF . ALGOL 60 frymëzoi shumë gjuhë që e pasuan atë. Tony Hoare vërejti: "... nuk ishte vetëm një përmirësim i paraardhësve të tij, por edhe pothuajse të gjithë pasardhësve të tij."  
* *1958–1962* : John McCarthy në MIT projektoi LISP-in .  Aftësitë e përpunimit të simboleve ofruan karakteristika të dobishme për kërkimin e inteligjencës artificiale. Në vitin 1962, versioni LISP 1.5 shënoi disa mjete: një interpretues të shkruar nga Stephen Russell dhe Daniel J. Edwards, një kompilues dhe asambler të shkruar nga Tim Hart dhe Mike Levin. 

Sistemet operative dhe softuerët e hershëm ishin shkruar në gjuhën assembly. Gjatë viteve 1960 dhe në fillim të viteve 1970, përdorimi i gjuhëve të nivelit të lartë për programimin e sistemeve ishte ende i diskutueshëm për shkak të kufizimeve të burimeve. Megjithatë, disa përpjekje kërkimore dhe industriale filluan të zhvendosnin fokusin drejt gjuhëve programuese të nivelit të lartë për programim sistemesh, si p.sh. BCPL, BLISS, B dhe C. BCPL, BLISS, B dhe  C.

BCPL(Gjuha Bazë e Kombinuar e Programimit), e projektuar në vitin 1966 nga Martin Richards në Universitetin e Kambrixhit u zhvillua fillimisht si një mjet shkrimi për kompajlerët.  Janë zhvilluar disa kompajlerë për të, dhe libri i Richards ofron njohuri të hollësishme mbi gjuhën dhe kompajlerin e saj.   BCPL jo vetëm që ishte një gjuhë me ndikim për programimin e sistemeve, e cila ende përdoret në kërkim, por gjithashtu shërbeu si bazë për hartimin e gjuhëve  , B dhe C.

BLISS (Gjuha Bazë për Implementimin e Softuerit të Sistemit) u zhvillua për kompjuterin PDP-10 të Korporatës së Pajisjeve Dixhitale (DEC) nga ekipi kërkimor i Universitetit Carnegie Mellon (CMU) nën drejtimin e W. A. Wulf. Një vit më vonë, në vitin 1970, ekipi i CMU-së zhvilloi kompajlerin BLISS-11.

Multics (Shërbim i Multipleksuar i Informacionit dhe Kompjuterizimit), një projekt i sistemit operativ me ndarje të kohës, përfshinte MIT, Bell Labs, General Electric (më vonë Honeywell ) dhe u drejtua nga Fernando Corbató nga MIT.  Multics u shkrua në gjuhën PL/I të zhvilluar nga IBM dhe Grupi i Përdoruesve të IBM.  Qëllimi i IBM ishte të plotësonte kërkesat e programimit të biznesit, shkencës dhe sistemeve. Kishte gjuhë të tjera që mund të ishin marrë në konsideratë, por PL/I ofroi zgjidhjen më të plotë edhe pse nuk ishte zbatuar.  Për vitet e para të projektit Multics, një nëngrup i gjuhës mund të kompilohej në gjuhën e asamblesë me kompiluesin e hershëm PL/I (EPL) nga Doug McIlory dhe Bob Morris nga Bell Labs.  EPL mbështeti projektin derisa të mund të zhvillohej një kompilues vetëndërtues për PL/I të plotë. 

Bell Labs u largua nga projekti Multics në vitin 1969 dhe zhvilloi një gjuhë programimi sistemesh B bazuar në konceptet e BCPL, të shkruar nga Dennis Ritchie dhe Ken Thompson . Ritchie krijoi njëkompilues vetëndërtues për B dhe shkroi sistemin operativ Unics (Shërbim i Unipleksuar i Informacionit dhe Kompjuterizimit) për një PDP-7 në B. Unics përfundimisht u shkrua Unix

Bell Labs filloi zhvillimin dhe zgjerimin e gjuhës C bazuar në B dhe BCPL. Kompiluesi i BCPL u transportua në Multics nga Bell Labs, dhe BCPL ishte një gjuhë e preferuar brenda laboratorëve. Fillimisht, u përdor një program front-end për kompiluesin B të Bell Labs ndërkohë që zhvillohej kompiluesi për C. Në vitin 1971, një PDP-11 i ri ofroi resurset e nevojshme për të përcaktuar zgjerime për B dhe për të rishkruar kompiluesin. Në vitin 1973, dizajni i gjuhës C ishte thelbësisht i përfunduar, dhe bërthama e Unix për PDP-11 u rishkrua në C. Steve Johnson filloi zhvillimin e "Portable C Compiler (PCC)" për të mbështetur ritransferimin e kompiluesve C në makina të reja. 

Programimi i orientuar nga objektet (OOP) ofroi disa mundësi interesante për zhvillimin dhe mirëmbajtjen e aplikacioneve. Konceptet OOP datojnë më herët, por ishin pjesë e shkencës së gjuhëve LISP dhe Simula .  Bell Labs u interesuan për OOP me zhvillimin e C++ .  C++ u përdor për herë të parë në vitin 1980 për programimin e sistemeve. Dizajni fillestar shfrytëzoi aftësitë e programimit të sistemeve të gjuhës C së bashku me konceptet e Simula-s.. Pajisjet e orientuara nga objektet u shtuan në vitin 1983.  Programi Cfront zbatoi një front-end C++ për kompiluesin e gjuhës C84. Në vitet pasuese u zhvilluan disa kompilues C++ ndërsa popullariteti i gjuhës C++ rritej.

Në shumë fusha aplikimi, ideja e përdorimit të një gjuhe të nivelit më të lartë u përhap shpejt. Për shkak të funksionalitetit në zgjerim të mbështetur nga gjuhët më të reja të programimit dhe kompleksitetit në rritje të arkitekturave kompjuterike, kompajlerët u bënë më kompleksë.

DARPA (Agjencia e Projekteve të Kërkimit të Avancuar të Mbrojtjes) sponsorizoi një projekt përpiluesi me ekipin kërkimor CMU të Wulf në vitin 1970. Dizajni PQCC i Përpiluesit të Cilësisë së Prodhimit - nga përkufizimet formale të gjuhës burimore dhe gjuhës së synuar. PQCC përpiqej të zgjerojë kuptimin e termit përpilues-përpilues përtej përdorimit të tij tradicional si gjenerator analizues (p.sh., Yacc ), por pa shumë sukses. Më saktë, PQCC mund të quhet një gjenerator përpiluesish.

Hulumtimi i PQCC mbi procesin e gjenerimit të kodit synonte të ndërtonte një sistem vërtetësisht automatik për të shkruar kompilues. Ky përpjekje zbuloi dhe dizajnoi strukturën e fazave të PQC. Kompiluesi BLISS-11 ofroi strukturën fillestare.[1] Faza përfshinte analiza (front end), përkthim të ndërmjetëm në makinë virtuale (middle end) dhe përkthim në objektivin përfundimtar (back end). TCOL u zhvillua për hulumtimin PQCC për të trajtuar konstrukte specifike të gjuhës në përfaqësimin ndërmjetëm.[2] Variacionet e TCOL mbështetën gjuhë të ndryshme. Projekti PQCC hulumtoi teknika të ndërtimit automatik të kompiluesve. Konceptet e dizajnit provuan të ishin të dobishme në optimizimin e kompiluesve dhe në kompiluesit për gjuhën e programimit Ada (që që nga viti 1995 është orientuar në objekt).

Dokumenti Ada STONEMAN formalizoi mjedisin e mbështetjes së programit (APSE) së bashku me kernelin (KAPSE) dhe versionin minimal (MAPSE). Një interpretues Ada, NYU/ED, mbështeti zhvillimin dhe përpjekjet për standardizim me Institutin Amerikan të Standardeve (ANSI) dhe Organizatat Ndërkombëtare të Standardeve (ISO). Zhvillimi fillestar i kompiluesit Ada nga Shërbimet Ushtarake të SHBA përfshinte kompiluesit brenda një mjedisi të integruar të dizajnit sipas linjave të dokumentit STONEMAN. Ushtria dhe Marina punuan në projektin Ada Language System (ALS) i cili ishte i synuar për arkitekturën DEC/VAX, ndërsa Forca Ajrore filloi me Ada Integrated Environment (AIE) e cila ishte e synuar për serinë IBM 370. Edhe pse projektet nuk dhanë rezultatet e dëshiruara, ato kontribuan në përpjekjen e përgjithshme për zhvillimin e Ada-s. 

Përpjekje të tjera për përpiluesin Ada filluan në Britani në Universitetin e Yorkut dhe në Gjermani në Universitetin e Karlsruhe. Në SHBA, Verdix (më vonë i blerë nga Rational) i dorëzoi Ushtrisë Sistemin e Zhvillimit Verdix Ada (VADS). VADS ofroi një sërë mjetesh zhvillimi duke përfshirë një përpilues. Unix/VADS mund të strehohej në një sërë platformash Unix si DEC Ultrix dhe Sun 3/60 Solaris të synuara për Motorola 68020 në një vlerësim të CECOM të Ushtrisë.  Shpejt pati shumë përpilues Ada të disponueshëm që kaluan testet e Validimit Ada. Projekti GNU i Fondacionit të Softuerit të Lirë zhvilloi Koleksionin e Përpiluesve GNU (GCC) i cili ofron një aftësi thelbësore për të mbështetur gjuhë dhe objektiva të shumëfishta. Versioni Ada GNAT është një nga përpiluesit Ada më të përdorur gjerësisht. GNAT është falas, por ka edhe mbështetje komerciale, për shembull, AdaCore, u themelua në vitin 1994 për të ofruar zgjidhje komerciale softuerike për Ada. GNAT Pro përfshin GNAT-in e bazuar në GNU GCC me një suitë mjetesh për të ofruar një mjedis të integruar zhvillimi .

Gjuhet e nivelit të lartë vazhduan të nxisin kërkimin dhe zhvillimin e kompiluesve. Fushat e fokusit përfshinin optimizimin dhe gjenerimin automatik të kodit. Tendencat në gjuhët e programimit dhe mjediset e zhvillimit ndikuan në teknologjinë e kompiluesve. Më shumë kompilues u përfshinë brenda shpërndarjeve të gjuhëve (PERL, Java Development Kit) dhe si një komponent i një IDE-je (VADS, Eclipse, Ada Pro). Marrëdhënia dhe ndërvarësia midis teknologjive u rritën. Shfaqja e shërbimeve web promovoi rritjen e gjuhëve për web dhe gjuhëve skript. Skriptet i kanë rrënjët në ditët e hershme të Ndërfaqeve të Linjës së Komandës (CLI), ku përdoruesi mund të jepte komanda për t’u ekzekutuar nga sistemi. Konceptet e User Shell u zhvilluan me gjuhë për të shkruar programe shell. Dizajnet e hershme të Windows ofronin një kapacitet të thjeshtë të programimit batch. Transformimi konvencional i këtyre gjuhëve përdorte një interpretues. Edhe pse nuk ishin shumë të përdorura, janë shkruar kompilues Bash dhe Batch. Kohët e fundit, gjuhë të sofistikuara të interpretuara u bënë pjesë e kutisë së veglave të zhvilluesve. Gjuhët moderne skript përfshijnë PHP, Python, Ruby dhe Lua. (Lua përdoret gjerësisht në zhvillimin e lojërave.) Të gjitha këto kanë mbështetje për interpretues dhe kompilues. 

"Kur fusha e përpiluesvet filloi në fund të viteve '50, fokusi i saj ishte i kufizuar në përkthimin e programeve të gjuhës së nivelit të lartë në kod makine ... Sot, fusha e përpiluesve është gjithnjë e më e ndërthurur me disiplina të tjera, duke përfshirë arkitekturën kompjuterike, gjuhët e programimit, metodat formale, inxhinierinë e softuerit dhe sigurinë kompjuterike."  Artikulli "Kërkimi i Përpiluesve: 50 Vitet e Ardhshme" vuri në dukje rëndësinë e gjuhëve të orientuara nga objektet dhe Java-s. Siguria dhe informatika paralele u përmendën midis objektivave të kërkimit në të ardhmen.

## Ndërtimi i përpiluesit 
Një kompilues zbatojnë një transformim formal nga një program burimor i nivelit të lartë në një program objektiv të nivelit të ulët. Dizajni i kompiluesit mund të përcaktojë një zgjidhje nga fillimi në fund ose të trajtojë një nëngrup të caktuar që ndërvepron me vegla të tjera të kompilimit, si p.sh. parapërpunuesit, asamblet dhe lidhësit (linkers). Kërkesat e dizajnit përfshijnë ndërfaqe të përcaktuara me rigorozitet, si brenda komponentëve të kompiluesit ashtu edhe jashtë, midis grupeve mbështetëse të veglave.

Në ditët e hershme, qasja e ndjekur për dizajnimin e kompiluesve ishte drejtpërdrejt e ndikuar nga kompleksiteti i gjuhës kompjuterike që duhej të përpunohej, përvoja e personit ose personave që e dizajnonin atë, dhe burimet e disponueshme. Kufizimet e burimeve çuan në nevojën për të kaluar përmes kodit burimor më shumë se një herë.

Një kompilues për një gjuhë relativisht të thjeshtë, i shkruar nga një person, mund të jetë një pjesë e vetme dhe monolitike e softuerit. Megjithatë, ndërsa gjuha burimore rritet në kompleksitet, dizajni mund të ndahet në një numër fazash të ndërvarura. Faza të veçanta ofrojnë përmirësime në dizajn duke fokusuar zhvillimin te funksionet e procesit të kompilimit.

### Përpilues njëkalimësh kundrejt përpiluesve me shumë kalime 
Klasifikimi i kompiluesve sipas numrit të kalimeve (passes) ka origjinën në kufizimet e burimeve të harduerit të kompjuterëve. Kompilimi përfshin kryerjen e shumë punëve, dhe kompjuterët e hershëm nuk kishin mjaftueshëm memorie për të përmbajtur një program që të bënte të gjitha këto punë. Si rezultat, kompiluesit u ndanë në programe më të vogla, secili duke bërë një kalim mbi kodin burimor (ose mbi një përfaqësim të tij) dhe duke kryer disa nga analizat dhe përkthimet e kërkuara.

Aftësia për të përpiluar në një kalim të vetëm kalim të vetëm është parë tradicionalisht si një avantazh, sepse e thjeshton punën e shkrimit të një përpiluesi, dhe përpiluesit njëkalimësh zakonisht kryejnë përpilimin më shpejt sesa  përpiluesit me shumë kalime. Për këtë arsye, pjesërisht i nxitur nga kufizimet e burimeve në sistemet e hershme, shumë gjuhë të hershme u dizajnuan posaçërisht në mënyrë që të mund të përpiloheshin në një kalim të vetëm (p.sh., Pascal ).

Në disa raste, dizajni i një veçorie të gjuhës mund të kërkojë që një kompilues të kryejë më shumë se një kalim mbi kodin burimor. Për shembull, konsideroni një deklaratë që shfaqet në linjën 20 të kodit burimor dhe që ndikon në përkthimin e një deklarate që shfaqet në linjën 10. Në këtë rast, kalimi i parë duhet të mbledhë informacion mbi deklaratat që shfaqen pas deklaratave që ato ndikojnë, ndërsa përkthimi aktual kryhet gjatë një kalimi të mëvonshëm.

Disavantazhi i përpilimit në një kalim të vetëm është se nuk është e mundur të kryhen shumë nga optimizimet e sofistikuara të nevojshme për të gjeneruar kod me cilësi të lartë. Mund të jetë e vështirë të numërosh saktësisht se sa kalime bën një përpilues optimizues. Për shembull, faza të ndryshme të optimizimit mund të analizojnë një shprehje shumë herë, por një shprehje tjetër të analizojnë vetëm një herë.

Ndarja e një kompiluesi në programe të vogla është një teknikë e përdorur nga studiuesit që janë të interesuar për të prodhuar kompilues që mund të provohen si të saktë. Prova e saktësisë së një grupi programesh të vogla shpesh kërkon më pak përpjekje sesa prova e saktësisë së një programi më të madh dhe ekuivalent të vetëm.

### Struktura e kompiluesit me tre faza 
qendër|parapamje|Dizajni i kompiluesit
Pavarësisht nga numri i saktë i fazave në dizajnin e përpiluesit, fazat mund t’i caktohen njërës prej tre stadive. Këto stade përfshijnë një front-end, një middle-end dhe një back-end.

* *Front-end (pjesa e përparme)* skanon të dhënat hyrëse dhe verifikon sintaksën dhe semantikën sipas një gjuhe burimore specifike. Për gjuhët e tipizuara statikisht, ajo kryen kontrollin e tipit duke mbledhur informacionin e tipit. Nëse programi i hyrjes është sintaksorisht i pasaktë ose ka një gabim tipi, ajo gjeneron mesazhe gabimi dhe/ose paralajmërimi, zakonisht duke identifikuar vendndodhjen në kodin burimor ku është zbuluar problemi; në disa raste, gabimi aktual mund të jetë (shumë) më herët në program. Aspektet e pjesës së përparme përfshijnë analizën leksikore, analizën sintaksore dhe analizën semantike. Pjesa e përparme e transformon programin e hyrjes në një përfaqësim të ndërmjetëm (IR) për përpunim të mëtejshëm nga ana e mesit. Kjo IR zakonisht është një përfaqësim i nivelit më të ulët të programit në lidhje me kodin burimor.
* *Pjesa e mesme* kryen optimizime në IR që janë të pavarura nga arkitektura e CPU-së që synohet. Kjo pavarësi e kodit burimor/kodit të makinës ka për qëllim të mundësojë që optimizimet gjenerike të ndahen midis versioneve të përpiluesit që mbështesin gjuhë të ndryshme dhe procesorëve të synuar. Shembuj të optimizimeve të pjesës së mesme janë heqja e kodit të padobishëm ( eliminimi i kodit të vdekur ) ose të paarritshëm ( analiza e arritshmërisë ), zbulimi dhe përhapja e vlerave konstante ( përhapja konstante ), zhvendosja e llogaritjes në një vend që ekzekutohet më rrallë (p.sh., jashtë një cikli) ose specializimi i llogaritjes bazuar në kontekst, duke prodhuar përfundimisht IR-në e "optimizuar" që përdoret nga pjesa e prapme.
* *Back end (pjesa e pasme)*  merr IR-në e optimizuar nga pjesa e mesme. Mund të kryejë më shumë analiza, transformime dhe optimizime që janë specifike për arkitekturën e CPU-së së synuar. Pjesa e prapme gjeneron kodin e montimit të varur nga objektivi, duke kryer alokimin e regjistrave në proces. Pjesa e prapme kryen planifikimin e udhëzimeve, i cili rirendit udhëzimet për të mbajtur njësitë e ekzekutimit paralel të zëna duke mbushur hapësirat e vonesës . Edhe pse shumica e problemeve të optimizimit janë të vështira për t'u përdorur nga NP, teknikat heuristike për zgjidhjen e tyre janë të zhvilluara mirë dhe të zbatuara në kompilues me cilësi prodhimi. Zakonisht, rezultati i një back end është kod makine i specializuar për një procesor dhe sistem operativ të caktuar.

Kjo qasje front/middle/back-end bën të mundur kombinimin e front-endeve për gjuhë të ndryshme me back-endet për CPU të ndryshme, duke ndarë njëkohësisht optimizimet e pjesës së mesme.  Shembuj praktikë të kësaj qasjeje janë Koleksioni i Kompiluesve GNU, Clang (kompilues C/C++ i bazuar në LLVM ),  dhe Amsterdam Compiler Kit, të cilat kanë front-ende të shumëfishta, optimizime të përbashkëta dhe back-ende të shumëfishta.

#### Pjesa e përparme 
[parapamje|Shembull Lexer dhe parser për [C (gjuhë programimi)|C. Duke u nisur nga sekuenca e karaktereve " `if(net>0.0)total+=net*(1.0+tax/100.0);` ", skaneri harton një sekuencë tokenësh dhe kategorizon secilën prej tyre, për shembull si , , , ose  . Sekuenca e fundit transformohet nga analizuesi në një pemë sintaksore, e cila më pas trajtohet nga fazat e mbetura të përpiluesit. Skaneri dhe analizuesi trajtojnë përkatësisht pjesët e rregullta dhe ato pa kontekst të gramatikës për C.]]
Pjesa e përparme analizon kodin burimor për të ndërtuar një përfaqësim të brendshëm të programit, të quajtur përfaqësim i ndërmjetëm (IR). Ai gjithashtu menaxhon tabelën e simboleve, një strukturë të dhënash që lidh çdo simbol në kodin burimor me informacionin shoqërues, siç janë vendndodhja, lloji dhe fushëveprimi.

Ndërsa frontend-i mund të jetë një funksion ose program i vetëm monolit, si në një analizues pa skaner, ai tradicionalisht është zbatuar dhe analizuar si disa faza, të cilat mund të ekzekutohen në mënyrë sekuenciale ose njëkohësisht. Kjo metodë është e favorizuar për shkak të modularitetit të saj dhe ndarjes së përgjegjësive . Më së shpeshti, frontend-i ndahet në tre faza: analiza leksikore (e njohur edhe si leksikim ose skanim), analiza sintaksore (e njohur edhe si skanim ose analizim) dhe analiza semantike . Leximi dhe analizimi përbëjnë analizën sintaksore (sintaksa e fjalëve dhe sintaksa e frazave, përkatësisht), dhe në raste të thjeshta, këto module (lexuesi dhe analizuesi) mund të gjenerohen automatikisht nga një gramatikë për gjuhën, megjithëse në raste më komplekse këto kërkojnë modifikim manual. Gramatika leksikore dhe gramatika e frazave zakonisht janë gramatika pa kontekst, gjë që e thjeshton ndjeshëm analizën, me ndjeshmërinë ndaj kontekstit që trajtohet në fazën e analizës semantike. Faza e analizës semantike është përgjithësisht më komplekse dhe e shkruar me dorë, por mund të automatizohet pjesërisht ose plotësisht duke përdorur gramatika të atributeve . Këto faza në vetvete mund të ndahen më tej: leximi si skanim dhe vlerësim, dhe analizimi si ndërtimi i një peme konkrete sintaksore (CST, pema e analizimit) dhe më pas transformimi i saj në një pemë abstrakte sintaksore (AST, pema e sintaksës). Në disa raste përdoren faza shtesë, veçanërisht *rindërtimi i rreshtave* dhe *përpunimi paraprak,* por këto janë të rralla.

Fazat kryesore të front end përfshijnë si në vijim:

* *Rindërtimi i rreshtit*Rindërtimi i rreshtit konverton sekuencën e karaktereve hyrëse në një formë kanonike, gati për parser-in. Gjuhët që heqin fjalët e tyre kyçe ose lejojnë hapësira arbitrare brenda identifikuesve kërkojnë këtë fazë. Analistët nga lart poshtë, me zbritje rekursive, të drejtuar nga tabela, të përdorur në vitet 1960, zakonisht lexonin burimin një karakter në të njëjtën kohë dhe nuk kërkonin një fazë të veçantë tokenizimi. Atlas Autocode dhe Imp (dhe disa implementime të ALGOL dhe Coral 66 ) janë shembuj të gjuhëve të hequra, përpiluesit e të cilave do të kishin një fazë *Rindërtimi të rreshtit* .
* *Parapërpunimi* mbështet zëvendësimin makro dhe përpilimin me kusht . Në mënyrë tipike, faza e parapërpunimit ndodh para analizës sintaksore ose semantike; p.sh. në rastin e C, parapërpunuesi manipulon tokenat leksikore në vend të formave sintaksore. Megjithatë, disa gjuhë si Scheme mbështesin zëvendësimet makro bazuar në format sintaksore.
* *Analiza leksikore* (e njohur edhe si *leksikim* ose *tokenizim* ) e ndan tekstin e kodit burimor në një sekuencë pjesësh të vogla të quajtura *tokena leksikore* .  Kjo fazë mund të ndahet në dy faza: *skanimi*, i cili segmenton tekstin hyrës në njësi sintaksore të quajtura *leksema* dhe u cakton atyre një kategori; dhe *vlerësimi*, i cili i konverton leksemat në një vlerë të përpunuar. Një token është një çift që përbëhet nga një *emër tokeni* dhe një *vlerë opsionale tokeni* .  Kategoritë e zakonshme të tokenave mund të përfshijnë identifikues, fjalë kyçe, ndarës, operatorë, fjalë literale dhe komente, megjithëse grupi i kategorive të tokenave ndryshon në gjuhë të ndryshme programimi . Sintaksa e leksemës është zakonisht një gjuhë e rregullt, kështu që një automat me gjendje të fundme i ndërtuar nga një shprehje e rregullt mund të përdoret për ta njohur atë. Softueri që bën analizën leksikore quhet analizues leksikor . Ky mund të mos jetë një hap i veçantë - mund të kombinohet me hapin e analizimit në analizimin pa skaner, në të cilin rast analizimi bëhet në nivelin e karaktereve, jo në nivelin e tokenit.
* *Analiza sintaksore* (e njohur edhe si *analizim* ) përfshin analizimin e sekuencës së tokenëve për të identifikuar strukturën sintaksore të programit. Kjo fazë zakonisht ndërton një pemë analizimi, e cila zëvendëson sekuencën lineare të tokenëve me një strukturë peme të ndërtuar sipas rregullave të një gramatike formale që përcaktojnë sintaksën e gjuhës. Pema e analizimit shpesh analizohet, plotësohet dhe transformohet nga fazat e mëvonshme në përpilues. 
* *Analiza semantike* shton informacion semantik në pemën e analizimit dhe ndërton tabelën e simboleve . Kjo fazë kryen kontrolle semantike siç janë kontrolli i tipit (kontrolli për gabime tipi), ose lidhja e objekteve (shoqërimi i referencave të variablave dhe funksioneve me përkufizimet e tyre), ose caktimi përfundimtar (që kërkon që të gjitha variablat lokale të inicializohen para përdorimit), refuzimi i programeve të pasakta ose lëshimi i paralajmërimeve. Analiza semantike zakonisht kërkon një pemë të plotë analizimi, që do të thotë se kjo fazë ndjek logjikisht fazën e analizimit dhe paraprin logjikisht fazën e gjenerimit të kodit, megjithëse shpesh është e mundur të palosen faza të shumëfishta në një kalim mbi kodin në një implementim të përpiluesit.

#### Pjesa e mesme 
Faza e mesme, e njohur gjithashtu si optimizuesi, kryen optimizime mbi përfaqësimin ndërmjetëm për të përmirësuar performancën dhe cilësinë e kodit makinë të prodhuar. Faza e mesme përmban ato optimizime që janë të pavarura nga arkitektura e CPU-së që synohet.

Fazat kryesore të fazës së mesme përfshijnë sa vijon:

* Analiza: Kjo fazë përfshin mbledhjen e informacionit mbi programin nga përfaqësimi i ndërmjetëm i nxjerrë nga të dhënat hyrëse; analiza e rrjedhës së të dhënave përdoret për të ndërtuar zinxhirë përdorimi-përcaktimi, së bashku me analizën e varësisë, analizën e pseudonimeve, analizën e pointer-ave, analizën e arratisjes, etj. Analiza e saktë është baza për çdo optimizim të kompiluesit. Grafiku i rrjedhës së kontrollit të çdo funksioni të kompiluar dhe grafiku i thirrjes së programit zakonisht ndërtohen gjithashtu gjatë fazës së analizës.
* Optimizimi: përfaqësimi i gjuhës së ndërmjetme transformohet në forma funksionalisht ekuivalente, por më të shpejta (ose më të vogla). Optimizimet më të njohura janë zgjerimi në linjë, eliminimi i kodit të vdekur, përhapja konstante, transformimi i lakut dhe madje edhe paralelizimi automatik .

Analiza e përpiluesit është parakusht për çdo optimizim të përpiluesit, dhe të dyja punojnë ngushtë së bashku. Për shembull, analiza e varësisë   është thelbësore për transformimin e lakut .

Shtrirja e analizës dhe optimizimeve të përpiluesit ndryshon shumë; fushëveprimi i tyre mund të variojë nga operimi brenda një blloku bazë, deri te procedurat e tëra, apo edhe i gjithë programi. Ekziston një kompromis midis granularitetit të optimizimeve dhe kostos së përpilimit. Për shembull, optimizimet e vrimave të syrit janë të shpejta për t'u kryer gjatë përpilimit, por ndikojnë vetëm në një fragment të vogël lokal të kodit dhe mund të kryhen në mënyrë të pavarur nga konteksti në të cilin shfaqet fragmenti i kodit. Në të kundërt, optimizimi ndërprocedural kërkon më shumë kohë përpilimi dhe hapësirë memorieje, por mundëson optimizime që janë të mundshme vetëm duke marrë në konsideratë sjelljen e shumë funksioneve njëkohësisht.

Analizat dhe optimizimet ndërprocedurale janë të zakonshme në përpiluesit modernë komercialë nga HP, IBM, SGI, Intel, Microsoft dhe Sun Microsystems . Softueri falas GCC u kritikua për një kohë të gjatë për mungesën e optimizimeve të fuqishme ndërprocedurale, por po ndryshon në këtë drejtim. Një tjetër përpilues me burim të hapur me infrastrukturë të plotë analize dhe optimizimi është Open64, i cili përdoret nga shumë organizata për qëllime kërkimore dhe komerciale.

Për shkak të kohës dhe hapësirës shtesë të nevojshme për analizën dhe optimizimet e përpiluesit, disa përpilues i anashkalojnë ato si parazgjedhje. Përdoruesit duhet të përdorin opsione për përpilim për t’i treguar qartë përpiluesit se cilat optimizime duhet të aktivizohen.

#### Pjesa e pasme 
Pjesa e pasme është përgjegjëse për optimizimet specifike të arkitekturës së CPU-së dhe për gjenerimin e kodit . 

Fazat kryesore të back end përfshijnë si në vijim:

* *Optimizime të varura nga makina*: optimizime që varen nga detajet e arkitekturës së CPU-së që synon kompiluesi.  Një shembull i spikatur janë optimizimet me vrima, të cilat rishkruajnë sekuenca të shkurtra të udhëzimeve të asamblerit në udhëzime më efikase.
* *Gjenerimi i kodit*: gjuha e ndërmjetme e transformuar përkthehet në gjuhën e daljes, zakonisht gjuha amtare e makinës së sistemit. Kjo përfshin vendime për burimet dhe ruajtjen, të tilla si vendosja se cilat variabla do të vendosen në regjistra dhe memorie dhe përzgjedhja dhe planifikimi i udhëzimeve të përshtatshme të makinës së bashku me mënyrat e tyre të adresimit (shih gjithashtu algoritmin Sethi-Ullman ). Gjenerimi i të dhënave për debugim mund të jetë gjithashtu i nevojshëm për të lehtësuar procesin edebugimin .

### Korrektësia e përpiluesit 
Korrektësia e përpiluesit është dega e inxhinierisë së softuerëve që merret me përpjekjen për të treguar se një përpilues sillet sipas specifikimit të gjuhës së tij.  Teknikat përfshijnë zhvillimin e përpiluesit duke përdorur metoda formale dhe përdorimin e testimit rigoroz (shpesh të quajtur validim i përpiluesit) në një përpilues ekzistues.

## Gjuha e kompiluar kundrejt gjuhës së interpretuar 
Gjuhët e programimit të nivelit të lartë zakonisht shfaqen duke pasur parasysh një lloj përkthimi : ose të dizajnuara si gjuhë e kompiluar ose gjuhë e interpretuar . Megjithatë, në praktikë rrallë ka diçka në një gjuhë që *kërkon* që ajo të kompilohet ose interpretohet ekskluzivisht, megjithëse është e mundur të dizajnohen gjuhë që mbështeten në riinterpretim në kohën e ekzekutimit. Kategorizimi zakonisht pasqyron implementimet më të njohura ose të përhapura të një gjuhe - për shembull, BASIC nganjëherë quhet gjuhë e interpretuar, dhe C një gjuhë e kompiluar, pavarësisht ekzistencës së kompiluesve BASIC dhe interpretuesve C. 

Interpretimi nuk e zëvendëson plotësisht kompilimin. Ai vetëm e fsheh atë nga përdoruesi dhe e bën atë gradual. Edhe pse një interpretues mund të interpretohet vetë, një grup udhëzimesh makine të ekzekutuara drejtpërdrejt është i nevojshëm diku në fund të pirgut të ekzekutimit (shih gjuhën e makinës ).

Për më tepër, për qëllime optimizimi, kompiluesit mund të përfshijnë funksionalitete të interpretuesit, dhe interpretuesit mund të përdorin teknika kompilimi paraprak. Për shembull, kur një shprehje mund të ekzekutohet gjatë kompilimit dhe rezultatet të futen në programin përfundimtar, kjo parandalon nevojën për ta rillogaritur çdo herë që programi ekzekutohet, duke përshpejtuar ndjeshëm ekzekutimin. Trendet moderne drejt kompilimit "në kohë reale" dhe interpretimit të bytecode-it shpesh e zbusin edhe më tej ndarjen tradicionale midis kompiluesve dhe interpretuesve. Meta-gjurmimi është një qasje automatike e sintezës së kompiluesve që shkon edhe më tej, duke mundësuar sintetizimin e një kompiluesi nga një interpretues gjuhe.

Disa specifikime gjuhësore përcaktojnë që implementimet duhet të përfshijnë një mundësi kompilimi; për shembull, Common Lisp .   Megjithatë, nuk ka asgjë në përkufizimin e Common Lisp që e ndalon interpretimin e tij. Disa gjuhë të tjera kanë veçori që janë shumë të lehta për t'u implementuar në një interpretues, por e bëjnë shkrimin e një kompiluesi shumë më të vështirë; për shembull, APL, SNOBOL4,  dhe shumë gjuhë skriptimi lejojnë programe të ndërtojnë kod burimor arbitrar gjatë ekzekutimit, duke përdorur operacione të rregullta mbi vargje, dhe pastaj ta ekzekutojnë këtë kod duke e kaluar tek një  funksion të veçantë vlerësimi . funksion të veçantë vlerësimi. Për të zbatuar këto veçori në një gjuhë të kompiluar, programet zakonisht duhet të shoqërohen me një  bibliotekë në kohën e ekzekutimit që përfshin një version të vetë kompiluesit.

## Llojet 
Një klasifikim i kompiluesve është sipas platformës në të cilën ekzekutohet kodi i tyre i gjeneruar. Kjo njihet si *platforma e synuar.*

Një kompilues *vendas* ose *i hostuar* është ai, rezultati i të cilit është menduar të ekzekutohet drejtpërdrejt në të njëjtin lloj kompjuteri dhe sistemi operativ në të cilin ekzekutohet vetë kompiluesi. Rezultati i një kompiluesi të kryqëzuar është projektuar të ekzekutohet në një platformë të ndryshme. Kompiluesit e kryqëzuar përdoren shpesh kur zhvillohen softuerë për sisteme të ngulitura që nuk synojnë të mbështesin një mjedis zhvillimi softuerësh.

Rezultati i një përpiluesi që gjeneron kod për një  makinë virtuale (VM) mund të ekzekutohet ose jo në të njëjtën platformë me kompiluesin që e ka prodhuar. Për këtë arsye, këto përpilues zakonisht nuk klasifikohen si vendas ose kryqëzues.

Gjuha e nivelit më të ulët që është objektivi i një kompiluesi mund të jetë vetë një gjuhë programimi e nivelit të lartë . C, e parë nga disa si një lloj gjuhe asambleje portative, është shpesh gjuha objektiv e kompiluesve të tillë. Për shembull, Cfront, kompiluesi origjinal për C++, përdori C si gjuhën e tij objektiv. Kodi C i gjeneruar nga një kompilues i tillë zakonisht nuk ka për qëllim të jetë i lexueshëm dhe i mirëmbajtur nga njerëzit, kështu që stili i indentit dhe krijimi i një kodi të ndërmjetëm C injorohen. Disa nga karakteristikat e C që e bëjnë atë një gjuhë të mirë objektiv përfshijnë direktivën , e cila mund të gjenerohet nga kompiluesi për të mbështetur debugging-un e burimit origjinal, dhe mbështetjen e gjerë të platformës së disponueshme me kompiluesit C.

Ndërsa një lloj i zakonshëm i përpiluesit gjeneron kod makine, ekzistojnë edhe shumë lloje të tjera:

* Kompiluesit burim-në-burim janë një lloj kompiluesi që merr një gjuhë të nivelit të lartë si të dhëna hyrëse dhe nxjerr një gjuhë të nivelit të lartë. Për shembull, një kompilues automatik paralelizues shpesh do të marrë një program me gjuhë të nivelit të lartë si të dhëna hyrëse dhe më pas do ta transformojë kodin dhe do ta shënojë atë me shënime paralele të kodit (p.sh. OpenMP ) ose konstrukte gjuhësore (p.sh. deklaratat `DOALL` të Fortran). Terma të tjerë për një kompilues burim-në-burim janë transcompiler ose transpiler. 
* Kompiluesit e kodit të bajtit kompilohen në gjuhën e asamblesë së një makine teorike, si disa implementime të Prolog-ut.
** Kjo makinë Prolog njihet edhe si Makina Abstrakte Warren (ose WAM).
** Kompilatorët e Bajtkodit për Java, Python janë gjithashtu shembuj të kësaj kategorie.
* Kompiluesit “just-in-time ” (kompiluesi JIT) e shtyjnë kompilimin deri në kohën e ekzekutimit. Kompiluesit JIT ekzistojnë për shumë gjuhë moderne, duke përfshirë Python, JavaScript, Smalltalk, Java, Microsoft , Gjuhën e Përbashkët të Ndërmjetme (CIL) të NET dhe të tjera. Një kompilues JIT përgjithësisht funksionon brenda një interpretuesi. Kur interpretuesi zbulon se një shteg kodi është "i nxehtë", që do të thotë se ekzekutohet shpesh, kompiluesi JIT do të thirret dhe do të kompilojë kodin 'e nxehtë' për performancë më të lartë
** Për disa gjuhë, siç është Java, aplikacionet kompilohen së pari duke përdorur një kompilues bajtokodi dhe dorëzohen në një përfaqësim të ndërmjetëm të pavarur nga makina. Një interpretues bajtokodi ekzekuton bajtokodin, por kompiluesi JIT do ta përkthejë bajtokodin në kod makine kur është e nevojshme performancë më e lartë.  &#x5B; '** &#x5D;
* Kompiluesit e harduerit (të njohur edhe si mjete sinteze) janë kompilues, hyrja e të cilëve është një gjuhë përshkrimi të harduerit dhe dalja e të cilëve është një përshkrim, në formën e një liste rrjeti ose ndryshe, i një konfigurimi hardueri.
** Prodhimi i këtyre kompiluesve synon harduerin e kompjuterit në një nivel shumë të ulët, për shembull një varg portash të programueshme në terren (FPGA) ose një qark të integruar të strukturuar specifik për aplikacionin (ASIC).  &#x5B; **' &#x5D; Kompilues të tillë quhen kompilues harduerësh, sepse kodi burimor që ata kompilojnë kontrollon në mënyrë efektive konfigurimin përfundimtar të harduerit dhe mënyrën e funksionimit të tij. Rezultati i kompilimit është vetëm një ndërlidhje e transistorëve ose tabelave të kërkimit .
** Një shembull i kompiluesit të pajisjeve është XST, Xilinx Synthesis Tool që përdoret për konfigurimin e FPGA-ve.  &#x5B; '** &#x5D; Mjete të ngjashme janë të disponueshme nga Altera,   Synplicity, Synopsys dhe shitës të tjerë të pajisjeve. &#x5B; **' &#x5D;
** Sistemet kërkimore përpilojnë nëngrupe të gjuhëve seriale të nivelit të lartë, të tilla si Python ose C++, direkt në logjikën dixhitale të paralelizuar. Kjo është zakonisht më e lehtë për t'u bërë për gjuhët funksionale ose nëngrupet funksionale të gjuhëve me shumë paradigma. 
* Një program që përkthen nga një gjuhë e nivelit të ulët në një të nivelit më të lartë është një dekompilues . 
* Një program që përkthehet në një format kodi objekti që nuk mbështetet në makinën e kompilimit quhet kompilues i kryqëzuar dhe përdoret zakonisht për të përgatitur kodin për ekzekutim në aplikacionet e softuerit të integruar.  &#x5B; ''* &#x5D;
* Një program që rishkruan kodin e objektit përsëri në të njëjtin lloj kodi objekti ndërsa aplikon optimizime dhe transformime është një rikompilues binar .

*Asamblerët,'' të cilët përkthejnë gjuhën e asamblerit të lexueshme nga njeriu në udhëzime të kodit të makinës të ekzekutuara nga hardueri, nuk konsiderohen kompilues.   (Programi invers që përkthen kodin e makinës në gjuhën e asamblerit quhet disassembler .)

## Shih edhe 
## Shënime dhe referenca 
## Shënime 
## Lexime të mëtejshme 
 

## Lidhje të jashtme 
* Qasje rritëse ndaj ndërtimit të kompilatoritnjë tutorial PDF
*   
*    që shpjegon ndryshimin kryesor konceptual midis kompiluesve dhe interpretuesve
*   
* Le të Ndërtojmë një Kompilator, nga Jack Crenshaw
*