Կոմպիլյատոր

համակարգչային ծրագիր է, որը ծրագրի սկզբնական տեքստը ձևափոխում է օբյեկտային կոդի

Կոմպիլյատորը (անգլ.՝ compiler) ծրագիր է, որը փոխակերպում է ծրագրավորման լեզվով գրված սկզբանական կոդը ( անգլ.՝ source code) այլ ծրագրային լեզվով(ելքային լեզվի, անգլ.՝ target language) կոդի, որը հիմնականում ունի բինար տեսք և հայտնի է օբյեկտային կոդ (անգլ.՝ object code) անվանմամբ։ Սկզբնական կոդի փոխակերպման ամենատարածված պատճառը այն է որ ստեղծվի կատարվող ծրագիր (անգլ.՝ executable program).

Թարգմանման համակարգ

Կոմպիլյատոր բառը հիմնականում օգտագործվում է այն ծրագրերի համար, որոնք սկզբնական կոդը բարձր մակարդակի ծրագրավորման լեզվից թարգմանում են ցածր մակարդակի լեզվի (օրինակ՝ ասսեմբլեր լեզվի կամ մեքենայական կոդի

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

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

Կոմպիլյատորը կարող է կատարել բոլոր նշված օպերացիաները՝

  • լեքսիկական վերլուծություն ( անգլ.՝ lexical analysis) - Այս փուլում սկզբնական ֆայլի սիմվոլների հաջորդականությունը փոխակերպվում է թոքենների հաջորդականության։
  • սինտակտիկական (քերականական) անալիզ (անգլ.՝ Parsing) - թոքենների հաջորդականությունը փոխակերպվում է վերլուծության ծառի (parse tree):
  • սեմանտիկական (իմաստային) անալիզ (անգլ.՝ semantic analysis) - վերլուծության ծառը մշակվում է իմաստը հաստատելու նմատակով։ Օրինակ՝ իդենտիֆիկատորների կապը դրանց հայտարարմանը, տիպերին, համատեղելիության ստուգումը և այլն։ Արդյունքը հիմնականում կոչվում է կոդի միրջանկյալ ներկայացում (անգլ.՝ intermediate representation) և կարող է լինել վերլուծության ծառի լրացում, նոր ծառ, աբստրակտ հրամանների խումբ կամ այլ բան՝ հարմար հետագա աշխատանքին։
  • կոդի օպտիմիզացիա ( անգլ.՝ code optimization) - կատարվում է ավելորդ կոնստրուկցիաների հեռացում և կոդի պարզեցում՝ իմաստը պահպանելով։
  • կոդի գեներացիա (անգլ.՝ code generation) - միջանկյալ ներկայացումից առաջանում է ելքային կոդ (անգլ.՝ target code)։

Ծրագիրը կարող է օգտագործել օպերացիոն համակարգի կողմից տրամադրված ծառայություններ (օրինակ գրադարաններ՝ ֆայլերի հետ աշխատելու համար, գրադարաններ՝ գրաֆիկական ինտերֆեյս ստեղծելու համար)։ Մեքենայական կոդի օբյեկտային ֆայլերը այլ օբյեկտային ֆայլերից ավելացնելու և դինամիկ գրադարանի մասին ինֆորմացիայի համար կատարվում է միացում (անգլ.՝ link)։ Միացում կատարվում է կապերի խմբագրիչով։ Կապերի խմբագրիչը կարող է լինել առանձին ծրագիր կամ կոմպիլյատորի մաս։ Այն ստեղծում է կատարվող ֆայլ ( անգլ.՝ executable file) և իրականացվում է հետևյալ ձևով՝

  1. օգտագործողի պահանջով ստեղծվում է օպերացիոն համակարգի միջուկում ստեղծվում է «պրոցես» օբյեկտ,
  2. օպերացիոն համակարգի բեռնիչը (անգլ.՝ loader) կատարում է հաջորդ գործողությունները
  3. կատարվող ֆայլը իրականացնում է
  4. բեռնում է հիշողության մեջ
  5. բեռնում է դինամիկ գրադարանի հիշողության մեջ
  6. կատարում է մեքենայական կոդի ծրագրի միացում դինամիկ գրադարանին
  7. ղեկավարումը փոխանցում է ծրագրին

Կոմպիլյատորի առավելությունները՝

  • ծրագրի կոմպիլյացիան կատարվում է մեկ անգամ
  • սարքում, որի համար կատարվում է կոմպիլյացիան, կոմպիլյատորի առկայություն չի պահանջվում։

Կոմպիլյատորի թերությունները՝

  • կոմպիլյացիան դանդաղ գործընթաց է
  • սկզբնական կոդում փոփոխություններ անելուց հետո պահանջվում է կրկնակի կոմպիլյացիա

Կոմպիլյացիա խմբագրել

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

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

Կոմպիլյատորի կառուցվածքը խմբագրել

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

Կոմպիլյատորի ելքը ( Compiler output ) խմբագրել

 
Նույն մուտքի դեպքում կոմպիլյատորի և ինտերպրետատորի ելքերը տարբեր են

Կոմպիլյատորի դասկարգումնեիրց մեկը դա պլատֆորմն է, որում գեներացվում է կատարվող կոդը։ Դա հայտնի է որպես ելքային(նշանակային) պլատֆորմ ( անգլ.՝ target platform) անվանմամբ։

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

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

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

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

 
Այս պարզ սխեման պատկերում է, թե ինչպես է ինֆորմացիան փոխակերպվում անալիզատորի(անգլ.՝ parser) կողմից։
Բարձր մակարդակի լեզուներով գրված ծրագրերը, կամ ուղղակիորեն իրականցվում են ինտերպրետատորի ինչ-որ մի տեսակով, կամ կոմպիլյատորի կողմից ձևափոխվում են մեքենայական կոդի՝ պրոցեսորի համար, որպեսզի այն կատարի։

Չնայած կոմպիլյատորների հիմանկան արդյունքը հարդվերի կողմից գործարկվող մեքենայական կոդն է, դրանց արդյունքը հաճախ կարող է ընդունել միջանկյալ տեսք՝ օբյեկտային կոդ (անգլ.՝ object code ) անվանմամբ։ Կոմպիլյացվող ծրագիրը սովորաբար օգտագործում է կառուցվող բլոկներ (ֆունկցիաներ) գրադարանում պահված այդպիսի օբյեկտային կոդի մոդուլներ.Կապերի խմբագրիչը (անգլ.՝ linker ) օգտագործում է գրադարանային ֆայլերը օբյեկտային ֆայլերի հետ միավորելու համար մեկ գործարկվող ( անգլ.՝ executable ) ֆայլում։

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

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

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

Բաշխման սկզբունք խմբագրել

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

Ինտերպրետացվող ծրագրերը կարող են բաշխվել սկզբնական կոդի տեսքով։ Այն պետք է թարգմանված լինի յուրաքանչյուր ելքային մեքենայում, որը շատ ժամանակ է տևում, բայց ծրագիրը տեղաբաշխում է անկախ մեքենայի ճարտարապետությունից։

Դինամիկ կոմպիլյացիա խմբագրել

Դինամիկ կոմպիլյացիան (անգլ.՝ Dynamic compilation) պրոցեսս է, որն օգտագործում է ծրագրավորման լեզուների որոշ իրականացումներ, որպեսզի ծրագրի կատարման ժամանակ բարձրացնի արդյունավետությունը։ Չնայած նրան, որ ծագել է ինքնածրագրավորման լեզուներում (անգլ.՝ Self programming language), լավագույն հաըտնի լեզուն, որն օգտագործում է այս մեթոդը դա Java-ն է։ Քանի որ մեքենայական կոդը դինամիկ կոմպիլյատորի արդյունքն է, այն կառուցված է օպտիմիզացված ծրագրի կատարման ժամանակ, դինամիկ կոմպիլյացիայի օգտագործումը թույլ է տալիս օպտիմիզացիա, էֆեկտիվության բարձրացման համար՝ անհասանելի կոմպիլյացաված լեզուներին, բացառությամբ պատծճենված կոդի (անգլ.՝ code duplication) կամ մետածրագրավորման (metaprogramming)։

Կրոս կոմպիլյատորներ խմբագրել

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

JIT կոմպիլյացիա խմբագրել

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


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

AOT-կոմպիլյացիա խմբագրել

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

Դեկոմպիլյացիա խմբագրել

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

Առնչվող մեթոդներ խմբագրել

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

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

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

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

Արտաքին հղումներ խմբագրել

 Վիքիպահեստն ունի նյութեր, որոնք վերաբերում են «Կոմպիլյատոր» հոդվածին։