Կոմպիլյատոր

***Կոմպիլյատորը*** *()* ծրագիր է, որը փոխակերպում է ծրագրավորման լեզվով գրված սկզբանական կոդը ( ) այլ ծրագրային լեզվով*(ելքային լեզվի, )* կոդի, որը հիմնականում ունի բինար տեսք և հայտնի է օբյեկտային կոդ () անվանմամբ։ Սկզբնական կոդի փոխակերպման ամենատարածված պատճառը այն է որ ստեղծվի կատարվող ծրագիր *().* 
thumb|left|upright=1.50| Թարգմանման համակարգ
*Կոմպիլյատոր*  բառը հիմնականում օգտագործվում է այն ծրագրերի համար, որոնք  սկզբնական կոդը բարձր մակարդակի ծրագրավորման լեզվից թարգմանում են ցածր մակարդակի լեզվի (օրինակ՝  ասսեմբլեր լեզվի կամ մեքենայական կոդի)։

Եթե կոմպիլյացված ծրագիրը կարող է աշխատել այնպիսի համակարգչում, որի համար պրոցեսորը կամ օպերացիոն համակարգը տարբեր է այն պրոցեսորից կամ օպերացիոն համակարգից որով կոմպիլյատորն է աշխատում, ապա այդպիսի կոմպիլյատորին անվանում են քրոսս-կոմպիլյատոր *( )*։

* Ծրագիրը, որը թարգմանում է ցածր մակարդակի լեզուն բարձր մակարդակի լեզվի, կոչվում է *դեկոմպիլյատոր ()*։
* Ծրագիրը, որը բարձր մակարդակի լեզուների միջև է կատարում թարգմանություն, կոչվում է *source-to-source կոմպիլյատոր ()։ *
* *Վերագրված լեզուն*  (rewriter) ծրագիր է, որը թարգմանում է արտահայտությունների տեսքը՝ առանց  լեզուն փոխելու։ 
* *Կոմպիլյատորի կոմպիլյատոր* *(compiler-compiler)* տերմինը երբեմն օգտագործվում է հղվելով *վերլուծության գեներատորի*  վրա։ Այս միջոցը հաճախ օգտագործվում է լեքսիկական անալիզի *( )* և անալիզատորի *()* ստեղծման համար։

|thumb|upright=1.50| Ծրագրի '''կոմպիլյացիա'''
thumb|Կապերի խմբագրիչի գործընթացը։
Կոմպիլյատորը կարող է կատարել բոլոր նշված օպերացիաները՝
* **լեքսիկական վերլուծություն** *( )* - Այս փուլում սկզբնական ֆայլի սիմվոլների հաջորդականությունը փոխակերպվում է թոքենների հաջորդականության։ 
* **սինտակտիկական** (քերականական) անալիզ *()* - թոքենների հաջորդականությունը փոխակերպվում է վերլուծության ծառի *(parse tree):*
* **սեմանտիկական** (իմաստային) անալիզ *()* - վերլուծության ծառը մշակվում է իմաստը հաստատելու նմատակով։ Օրինակ՝ իդենտիֆիկատորների կապը դրանց հայտարարմանը, տիպերին, համատեղելիության ստուգումը և այլն։ Արդյունքը հիմնականում կոչվում է կոդի միրջանկյալ ներկայացում *()* և կարող է լինել վերլուծության ծառի լրացում, նոր ծառ, աբստրակտ հրամանների խումբ կամ այլ բան՝ հարմար հետագա աշխատանքին։
* **կոդի օպտիմիզացիա** *( )* - կատարվում է ավելորդ կոնստրուկցիաների հեռացում և կոդի պարզեցում՝ իմաստը պահպանելով։
* **կոդի գեներացիա** *()* - միջանկյալ ներկայացումից առաջանում է ելքային կոդ *()*։


Ծրագիրը կարող է օգտագործել օպերացիոն համակարգի կողմից տրամադրված ծառայություններ (օրինակ գրադարաններ՝ ֆայլերի հետ աշխատելու համար, գրադարաններ՝ գրաֆիկական ինտերֆեյս ստեղծելու համար)։ Մեքենայական կոդի օբյեկտային ֆայլերը այլ օբյեկտային ֆայլերից ավելացնելու  և դինամիկ գրադարանի մասին ինֆորմացիայի համար կատարվում է միացում *()*։ Միացում կատարվում է կապերի խմբագրիչով։ Կապերի խմբագրիչը կարող է լինել առանձին ծրագիր կամ կոմպիլյատորի մաս։ Այն ստեղծում է կատարվող ֆայլ *( )* և իրականացվում է հետևյալ ձևով՝ 
# օգտագործողի պահանջով ստեղծվում է օպերացիոն համակարգի միջուկում ստեղծվում է «պրոցես» օբյեկտ,
# օպերացիոն համակարգի բեռնիչը *()* կատարում է հաջորդ գործողությունները
# կատարվող ֆայլը իրականացնում է
# բեռնում է հիշողության մեջ
# բեռնում է դինամիկ գրադարանի հիշողության մեջ
# կատարում է մեքենայական կոդի ծրագրի միացում դինամիկ գրադարանին
# ղեկավարումը փոխանցում է ծրագրին
Կոմպիլյատորի առավելությունները՝
* ծրագրի կոմպիլյացիան կատարվում է մեկ անգամ
* սարքում, որի համար կատարվում է կոմպիլյացիան, կոմպիլյատորի առկայություն չի պահանջվում։
Կոմպիլյատորի թերությունները՝
* կոմպիլյացիան դանդաղ գործընթաց է
* սկզբնական կոդում փոփոխություններ անելուց հետո պահանջվում է կրկնակի կոմպիլյացիա

## Կոմպիլյացիա
Կոմպիլյատորը թույլատրում է մշակել ծրագիր, որը մեքենայից անկախ է *()*։ Քանի դեռ չկար FORTRAN-ը՝ առաջին բարձր-մակարդակի լեզուն, 1950-ականներին մեքենայից կախված ասսեմբլեր լեզուն լայն տարածում ոըներ։ Քանի որ ասսեմբլեր լեզուն ավելի շատ աբստրակցիա է և չի կարող աշխատել նույն ճարտարապետությունում մեքենայական կոդի նման, դրա համար այն պետք է փոխվի կամ վերագրվի, որպեսզի ծրագիրը կատարվի այլ համակարգչի ճարտարապետությունում։

Բարձր մակարդակի լեզուների առաջացման հետ՝ *FORTRAN-ին* հաջորդող, ինչպիսիք են COBOL, C, և BASIC ծրագրերը կարող են գրել մեքենայից անկախ սկզբնական ծրագրեր։ Կոպիլյատորը թարգմանում  է բարձր մակարդակի սկզբնական ծրագիրը ելքային ծրագիրը մեքենայական լեզվի՝ հատուկ հարդվերի համար։ Երբ ելքային ծրագիրը *()* գեներացված է, օգտագործողը կարող է ծրագիրը կատարել։

### Կոմպիլյատորի կառուցվածքը
thumb|upright=4.25| Ծրագրի թարգմանման փուլերը
Կոմպիլյատորը ստուգում է կոդի շարահյուսությունը, գեներացնում է էֆեկտիվ օբյեկտային կոդ, կատարում է  run-time օրգանիզացիա և  ձևավորում է ելքը համապատասխան ասսեմբլերի և դինամիկ կապերի խմբագրիչի կոնվենցիաների։ Կոմպիլյատորը բաղկացած է՝
* *The front end *: Ստուգում է շարահյուսություն և սեմանտիկա, գեներացնում է միջանկյալ ներկայացում կամ սկզբնական կոդի IR մշակման համար՝ *middle-end *-ով։ Կատրում է տիպի ստուգում՝ հավաքելով տիպի մասին ինֆորմացիա։ Գեներացնում է սխալները և զգուշացումները, եթե այդպիսիք կան։ *front end*-ի ասպեկտներն են լեքսիակակն վերլուծությունը, շարահյուսական վերլուծությունը և սեմանտիկական վերլուծությունը։
* *The middle end*: Ստուգում է օպտիմիզացիան, այդ թվում հեռացնելով անիմաստ և անհասնաելի կոդը, հաստատուն փոփոխականների հաըտնաբերումը և բազմացումը, հաշվարկի տեղաբաշխումը քիչ կատարվող տեղերի մասերում  *(օր․՝ loop-ից ելքը)*, կոնտեքստի հիման վրա հաշվարկի սպեցալիզացիան։ Գեներացնում է ևս մեկ միջանկյալ ներկայացում backend-ի համար։
* *The back end *: Գեներացնում է ասսեմբլեր կոդ, մշակման մեջ կատարելով ռեգիստրային տեղաբաշխում *( )*։ Օպտիմիզացնում է հարդվերի իրականացնող ելքային կոդը *(  )։*

## Կոմպիլյատորի ելքը ( Compiler output )
thumb|upright=6.25| Նույն մուտքի դեպքում կոմպիլյատորի և ինտերպրետատորի ելքերը տարբեր են
Կոմպիլյատորի դասկարգումնեիրց մեկը դա պլատֆորմն է, որում գեներացվում է կատարվող կոդը։ Դա հայտնի է որպես ելքային(նշանակային) պլատֆորմ *( )*  անվանմամբ։

Հարազատ կոմպիլյատորի ելքը նախատեսված է անմիջապես նույն համակարգչի և օպերացիոն համակարգում աշխատելու համար։ Կրոսս կոմպիլյատորի ելքը նախատեսված է տարբեր պլատֆորմներում աշխատելու համար։

Կոմպիլյատորի ելքը, որն առաջացնում է վիտուալ մեքենայի համար կոդ, նույն պլատֆորմի համար կարող է կատրվել կամ չի կարող, քանի որ կոմպիլյատորն է առաջացրել  այն։ Այդ պատճառով էլ հիմնականում չեն դասակարգվում, ինչպես հարազատ *( )*  կամ կրոսս *()* կոմպիլյատորները։

Ցածր մակարդակի լեզուն, որը կոմպիլյատորի ելքն է, կարող է ինքնին լինել բարձր մակարդակի լեզու։ C-ն հաճախ դիտարկվում է փողադրելի ասսեմբլեր, որը կարող է լինել կոմպիլյատորի ելքային լեզու։

## Կոմպիլյատորների և ինտերպրետատորների համեմատումը

thumb|upright=1.25| Այս պարզ սխեման պատկերում է, թե ինչպես է ինֆորմացիան փոխակերպվում անալիզատորի() կողմից։

Բարձր մակարդակի լեզուներով գրված ծրագրերը, կամ ուղղակիորեն իրականցվում են ինտերպրետատորի ինչ-որ մի տեսակով, կամ կոմպիլյատորի կողմից ձևափոխվում են մեքենայական կոդի՝ պրոցեսորի համար, որպեսզի այն կատարի։ 
Չնայած կոմպիլյատորների հիմանկան արդյունքը հարդվերի կողմից գործարկվող մեքենայական կոդն է, դրանց արդյունքը հաճախ կարող է ընդունել միջանկյալ տեսք՝ օբյեկտային կոդ *( )* անվանմամբ։ Կոմպիլյացվող ծրագիրը սովորաբար օգտագործում է կառուցվող բլոկներ (ֆունկցիաներ) գրադարանում պահված այդպիսի օբյեկտային կոդի մոդուլներ.Կապերի խմբագրիչը *( )* օգտագործում է գրադարանային ֆայլերը օբյեկտային ֆայլերի հետ միավորելու համար մեկ գործարկվող *(  )* ֆայլում։


Երկուսն էլ՝ կոմպիլյատորները և ինտերպրետատորները հիմնականում սկզբնական կոդը վերածում են թոքենների *()*, երկուսն էլ կարող են գեներացնել վերլուծության ծառ *()*, և երկուսն էլ կարող են գեներացնել անմիջական հրահանգներ (ստեկային մեքենայի համար, կամ այլ միջոցներով)։ Հիմնական տարբերությունը այն է, որ կոմպիլյացվող համակարգերը, այդ թվում լինկերը, գեներացնում են ակախ գործող մեքենայական կոդի ծրագիր, մինչ դեռ ինտերպրետացվող համակարգերը դրա փոխարեն իրականացնում են գործողություններ նկարագրված բարձր մակարդակի լեզուներով։

Կոմպիլյատորը գեներացնում է միջանկյալ օբյեկտային ծրագիր, մինչդեռ ինտերպրետատորը միջանկյալ օբյեկտային ծրագիր չի գեներացնում։

Կոմպիլյատորը փոխակերպում է միանգամից ամբողջ սկզբնական կոդը։ Արդյունքը ստացվում է մեկ կամ մի քանի օբյեկտային կոդի ֆայլեր։ Ինտերպրետատորը նույնպես փոխակերպում է սկզբնական կոդը,սակայն տող առ տող։ Երբ առաջին տողը արդեն փոխակերպված է, այն միանգամից կատարվում է։
Մեկ անգամ կոմպիլյացնել և կատարել ցանկացած ժամանակ։ Կոմպիլյացվող ծրագիրերն ամեն անգամ չեն կոմպիլյացվում։ Ինտերպրետացվող ծրագրերը ինտերպրետացվում են տող առ տող ամեն անգամ, երբ դրանք կատարում են։
Կոմպիլյաորը չի թույլատրում գործարկել ծրագիրը, քանի դեռ այն լիովին անսխալ է։ Ինտերպրետատորը կատարում է ծրագիրը առաջին տողից սկսած և դադարում է միայն այն դեպքում, երբ հանդիպում է սխալ։

## Բաշխման սկզբունք
Կոմպիլյատորը սկզբնական կոդը փոխակերպում է բինար ինստրուկցիաների, հատուկ պրոցեսսորի համար, դարձնելով այն ավելի քիչ տեղափոխելի*( portable)*։ Այդ փոխակերպումը տեղի է ունենում միայն մեկ անգամ և դրանից հետո նույն բինար ինստրուկցիաները տեղաբաշխում են օգտագործողի մեքենայում, որտեղ այն կարողանում է կատարվել առանց հետգա թարգմանությունների։Կրոսս կոմպիլյատորները կարողանում են գեներացնել բինար կոդ օգտագործողի մեքենայի համար, անգամ եթե այն ունի այլ պրոցոսսոր քան մեքենան, որտեղ կոդը կոմպիլյացվում է։ Ինտերպրետացվող ծրագրերը կարող են բաշխվել սկզբնական կոդի տեսքով։ Այն պետք է թարգմանված լինի յուրաքանչյուր ելքային մեքենայում, որը շատ ժամանակ է տևում, բայց ծրագիրը տեղաբաշխում է անկախ մեքենայի ճարտարապետությունից։

## Դինամիկ կոմպիլյացիա

**Դինամիկ կոմպիլյացիան ** *()* պրոցեսս է, որն օգտագործում է ծրագրավորման լեզուների որոշ իրականացումներ, որպեսզի ծրագրի կատարման ժամանակ բարձրացնի արդյունավետությունը։ Չնայած նրան, որ ծագել է ինքնածրագրավորման լեզուներում *()*, լավագույն հաըտնի լեզուն, որն օգտագործում է այս մեթոդը դա Java-ն է։ Քանի որ մեքենայական կոդը դինամիկ կոմպիլյատորի արդյունքն է, այն կառուցված է օպտիմիզացված ծրագրի կատարման ժամանակ, դինամիկ կոմպիլյացիայի օգտագործումը թույլ է տալիս օպտիմիզացիա, էֆեկտիվության բարձրացման համար՝ անհասանելի կոմպիլյացաված լեզուներին, բացառությամբ պատծճենված կոդի *()* կամ մետածրագրավորման *([[Մետածրագրավորում|metaprogramming]])*։

## Կրոս կոմպիլյատորներ

**Cross compiler**-ը *(միջկոմպիլյատորը)* կոմպիլյատոր է, որը ստեղծում է կատարվող կոդ այնպիսի պլատֆորմի համար, որը տարբեր է այն պլատֆորմից, որի վրա աշխատում է այդ կոմպիլյատորը։ Միջկոմպիլյատորի գործիքներն օգտագործվում են ներդրվող համակարգերի կատարվող կոդեր գեներացնելու համար։ Այն օգտագործվում է այնպիսի պլատֆորմների համար, որոնք չեն կարող ապահովել այս գործողությունների իրականացումը (օր․ միկրոկոնտրոլերները)։

## JIT կոմպիլյացիա

**JIT-կոմպիլյացիան** *()*, դինամիկ կոմպիլայցիան *( )* ծրագրի կատարման ժամանակ արված կոմպիլյացիա է՝ այլ ոչ թե մինչև ծրագրի կատարումը։ Շատ հաճախ այն բաղկացած է մեքենայական կոդի թարգմանությունից, բայց կարող է վերաբերվել նաև այլ ֆորմատի թարգմանությանը։

JIT-կոմպիլյացիան մեքենայակն կոդը թարգմանելու երկու ավանդական գաղափարների կոմբինացիա է՝ AOT-կոմպիլյացիա և ինտերպրետացիա, և իր մեջ համատեղում է երկուսի որոշ առավելություններ և թերություններ։ Կոպիտ ասած, JIT-կոմպիլյացիան համատեղում է կոմպիլյացված կոդի արագությունը ինտերպրետացիայի ճկունության հետ, ինտերպրետատորի հավելյալ ծախսերի հետ և լրացուցիչ կոմպիլյացիայի ծախսերը (ոչ միայն իներպրետացիայի)։ JIT-կոմպիլյացիան դինամիկ կոմպիլյացիայի տեսակ է, այդպիսով JIT-կոմպիլյացիայի տեսությունում կարող է տալ ավելի արագ կատարում քան ստատիկ կոմպիլացիան։ Ինտերպրետացիան և JIT-կոմպիլյացիան հատկապես համապատասխանում են դինամիկ ծրագրավորման լեզուների համար, այդ դեպքում runtime համակարգը կարող է կարգավորել late-bound տվյալների տիպերը և երաշխավորել կատարման անվտանգությունը։


## AOT-կոմպիլյացիա

**AOT-կոմպիլյացիան** *() կոմպիլյացիայի տեսակ է, որը օգտագործում է Ahead of Time Compilation (իրականացում կոմպիլյացիայից առաջ)։ Օգտագործվում է ինչպես բարձր մակարդակի լեզուների համար, ինչպիսին են [[C]]-ն և С++-ը կամ Pascal-ը, այնպես էլ միջանկյալ լեզունների կոմպիլյացիայի համար, ինչպիսին են բայթկոդ *Java, .NET Common, Intermediate Language (CIL), IBM System/38, IBM System i։*

== Դեկոմպիլյացիա ==

</div>Գոյություն ունեն ծրագրեր, որոնք լուծում են հակառակ խնդիրը՝ ցածր մակարդակի լեզվից բարձրմակարդակային լեզվի թարգմանությունը։ Այդպիսի գործընթացը կոչվում է *'դեկոմպիլյացիա**, ինչպես նաև դեկոմպիլյատոր։ քանի որ կոմպիլյացիան կորուստներով գործընթաց է, սկզբանակն կոդը ճշգրիտ վերականգնել ընդհանուր դեպքում հնարավոր չէ։ Ավելի արդյունավետ է [[բայթկոդ]]ում դեկոմպիլյացնել ծրագիրը։

== Առնչվող մեթոդներ ==
**Ասսեմբլեր լեզու** ''(անգլ.՝ assembly language)''՝ ցածր մակարդակի ծրագրավորման լեզու, մեքենայական լեզվի սիմվոլիկ ներկայացնում։ Ասսեմբլերը թույլ է տալիս գրել կարճ և արագ կատարվող ծրագրեր, մեծ մասամբ ասսեմբլերով գրվում են այնպիսի ծրագրեր, որոնք ապահովում են մեքենայական մասի արդյունավետությունը

Ծրագիրը, որը թարգմանում է ցածր մակարդակի լեզուն բարձր մակարդակի կոչվում է **դեկոմպիլյատոր** ''(decompiler)'' :

Ծրագիրը որը կատարում է թարգմանում բարձր մակարդակի լեզուների միջև, կոչվում են  **source to source կոմպիյատոր** ''(source to source translator, language converter կամ language rewriter)''։

Եթե կոմպիյացված ծրագիրը կարող է աշխատել այնպիսի համակարգչում, որի համար պրոցոսսորը կամ օպերացիոն համակարգը տարբեր է, դրանով որով կոմպիլյատորն աշխատում է, հայտնի է որպես **կրոսս-կոմպիլյատոր*' *( cross-compiler)*։

== Արտաքին հղումներ ==
* DMOZ
* [http://scheme2006.cs.uchicago.edu/11-ghuloum.pdf Incremental Approach to Compiler Construction]
* [http://la-samhna.de/library/compile/index.html Compile-Howto]
* *Basics of Compiler Design ''
*  
* 
* Let's Build a Compiler
* Forum about compiler development 

Կատեգորիա:Ամերիկյան հայտնագործություններ
Կատեգորիա:Ծրագրային գրադարաններ
Կատեգորիա:Կազմարկիչներ