Ve vědě o počítačích , je kompilátor je program, který převádí zdrojový kód do objektového kódu . Obecně je zdrojový kód napsán v programovacím jazyce ( zdrojový jazyk ), má vysokou úroveň abstrakce a je snadno srozumitelný lidem. Objektový kód je obecně psán v jazyce nižší úrovně (nazývaném cílový jazyk ), například v assembleru nebo strojovém jazyce , aby bylo možné vytvořit program spustitelný strojem.
Kompilátor provádí následující operace: lexikální analýza , předzpracování ( předzpracování ), syntaktická analýza ( analýza ), sémantická analýza a optimalizace generování kódu . Po kompilaci často následuje krok úpravy odkazu , který vygeneruje spustitelný soubor. Když je kompilovaný program (objektový kód) spuštěn v počítači, jehož procesor nebo operační systém se liší od procesoru nebo operačního systému kompilátoru, nazývá se to křížová kompilace .
Existují dvě možnosti kompilace:
odpovídající montážní kód
program po kompilaci - jazyk stroje zobrazený v šestnáctkové soustavě
Počáteční počítačový software byl napsán v montážním jazyce . Programovací jazyky nejvyšší úrovně (v abstrakce vrstvách ) nebyla vynalezena až výhody schopnosti opětovného využití softwaru na různých typů procesorů se staly mnohem důležitější než náklady na zápis do ‚překladače. Velmi omezená kapacita paměti raných počítačů také představovala několik technických problémů při vývoji překladačů.
Na konci 50. let se poprvé objevily programovací jazyky nezávislé na strojích. Následně je vyvinuto několik experimentálních překladačů. První překladač, systém A-0 (pro jazyk A-0), napsal Grace Hopper v roce 1952. Předpokládá se, že tým FORTRAN vedený Johnem Backusem z IBM vyvinul první úplný překladač v roce 1957. COBOL , vyvinutý v roce 1959 a je do značné míry založen na myšlenkách Grace Hopperové a je prvním jazykem, který má být sestaven na několika architekturách.
V několika aplikačních oblastech myšlenka používání jazyka s vyšší úrovní abstrakce rychle rozšířila. S nárůstem funkčnosti podporovaným novějšími programovacími jazyky a zvyšující se složitostí počítačové architektury se překladače stávají stále složitějšími.
V roce 1962 vytvořili Tim Lart a Mike Levin na Massachusetts Institute of Technology (MIT) pro Lisp první kompilátor s vlastním hostitelem - schopný kompilace do objektového kódu, vlastního zdrojového kódu vyjádřeného v jazyce vysoké úrovně . Počínaje sedmdesátými léty bylo velmi běžné vyvíjet kompilátor v jazyce, který byl určen ke kompilaci, což z Pascal a C dělalo velmi populární vývojové jazyky.
Můžeme také použít jazyk nebo prostředí specializované na vývoj překladačů: mluvíme během metakompilačních nástrojů a používáme například překladač překladačů . Tato metoda je zvláště užitečná pro vytvoření prvního kompilátoru nového jazyka; používání přizpůsobeného a přísného jazyka pak usnadňuje vývoj a vývoj.
Hlavním úkolem kompilátoru je vytvořit správný objektový kód, který bude spuštěn v počítači. Většina překladačů umožňuje optimalizovat kód, to znamená, že se bude snažit zlepšit rychlost provádění nebo snížit obsazení paměti programem.
Obecně je zdrojový jazyk „vyšší úrovně“ než cílový jazyk, to znamená, že představuje vyšší úroveň abstrakce. Kromě toho je zdrojový kód programu obvykle distribuován v několika souborech.
Kompilátor pracuje na základě analýzy a syntézy: namísto nahrazení každé konstrukce zdrojového jazyka ekvivalentní řadou konstrukcí cílového jazyka začíná analýzou zdrojového textu a vytvořením mezilehlé reprezentace , kterou následně převede do cílového jazyka. .
Kompilátor je rozdělen na alespoň dvě části: přední (nebo přední) část, někdy nazývanou „stub“, která čte zdrojový text a vytváří mezilehlou reprezentaci; a zadní (nebo koncová) část, která prochází touto reprezentací a vytváří cílový text. V ideálním kompilátoru je přední část nezávislá na cílovém jazyce, zatímco zadní část je nezávislá na zdrojovém jazyce. Někteří kompilátoři provádějí podstatné zpracování na prostřední části a stávají se samostatnou centrální částí, nezávisle na zdrojovém jazyce i cílovém stroji. Můžeme tedy psát překladače pro celou řadu jazyků a architektur sdílením centrální části, ke které připojujeme přední část pro každý jazyk a zadní část pro každou architekturu.
Fáze kompilace zahrnují:
Přední část tvoří lexikální, syntaktická a sémantická analýza, přechod prostředním jazykem a optimalizace. Generování kódu a propojení je poslední část.
Tyto různé kroky znamenají, že kompilátoři jsou stále předmětem výzkumu.
Implementace (realizace beton) programovacího jazyka může být interpretován nebo kompilován. Tato realizace je kompilátor nebo tlumočník a programovací jazyk může mít jednu implementaci kompilovanou a jinou interpretovanou.
Mluvíme o kompilaci, pokud je překlad proveden před provedením (princip smyčky je poté přeložen jednou), a o interpretaci, pokud je překlad dokončen krok za krokem, během provádění (prvky smyčky jsou poté zkoumány pro každé použití) .
Interpretace je užitečná pro ladění nebo pokud jsou zdroje omezené. V provozu je vhodnější kompilace.
První překladače byly psány přímo v assembleru , což je elementární symbolický jazyk odpovídající instrukcím cílového procesoru a některé mírně vyvinutější řídicí struktury. Tento symbolický jazyk musí být sestaven (nekompilován) a propojen, aby se získala spustitelná verze. Díky své jednoduchosti stačí k převodu na strojové instrukce jednoduchý program.
Aktuální překladače jsou obvykle psány v jazyce, který mají být kompilovány; například kompilátor C je napsán v C, SmallTalk v SmallTalk, Lisp v Lisp atd. Při realizaci kompilátoru je učiněn rozhodující krok, když je kompilátor pro jazyk X dostatečně kompletní, aby se sám kompiloval: pak již nezávisí na jiném jazyce (dokonce ani na assembleru), který má být vytvořen.
Je těžké odhalit chybu kompilátoru. Například pokud má kompilátor C chybu, programátoři C budou mít přirozeně tendenci zpochybňovat svůj vlastní zdrojový kód, nikoli kompilátor. Horší je, že pokud tento buggy kompilátor (verze V1) kompiluje nebuggy kompilátor (verze V2), mohl by být bugován kompilovaný spustitelný soubor (podle V1) kompilátoru V2. Přesto je jeho zdrojový kód dobrý. Bootstrap proto vyžaduje kompilátory programátorům, aby se vyhnula chybám stávajících překladačů.
Klasifikace překladačů podle počtu průchodů je způsobena nedostatkem hardwarových prostředků počítačů. Kompilace je nákladný proces a dřívější počítače neměly dostatek paměti k uložení programu, který musel tuto práci dělat. Překladače tak byly rozděleny do podprogramů, které každý přečetl ze zdroje, aby dokončil různé fáze lexikální analýzy , syntaktické analýzy a sémantické analýzy .
Schopnost kombinovat vše do jednoho průchodu byla považována za výhodu, protože zjednodušuje psaní kompilátoru, který obecně běží rychleji než kompilátor s více průchody. Vzhledem k omezeným zdrojům časných systémů bylo mnoho jazyků speciálně navrženo tak, aby je bylo možné kompilovat v jednom průchodu (např. Jazyk Pascal ).
Nelineární struktura programuV některých případech vyžaduje určitá vlastnost jazyka, aby jeho překladač provedl více než jeden průchod. Zvažte například prohlášení na řádku 20 zdroje, které ovlivňuje překlad příkazu na řádku 10 . V tomto případě by měl první průchod shromažďovat informace o deklaracích, zatímco skutečný překlad probíhá pouze během následujícího průchodu.
OptimalizaceRozdělení kompilátoru na malé programy je technika používaná výzkumníky, kteří se zajímají o výrobu efektivních překladačů. Je to proto, že nevýhodou kompilace s jedním průchodem je, že neumožňuje provedení většiny sofistikovaných optimalizací potřebných k vygenerování vysoce kvalitního kódu. Potom bude obtížné přesně spočítat počet průchodů, které provádí optimalizační kompilátor.
Rozdělení demonstrace opravyDemonstrace správnosti řady malých programů často vyžaduje menší úsilí než prokázání správnosti ekvivalentního většího jediného programu.
Kompilátor kompilátoru je program, který může generovat některou nebo všechny jeho části. Můžete například zkompilovat základy jazyka a zbytek použít pomocí základů jazyka.
V závislosti na použití a stroji, který bude program spouštět, možná budete chtít optimalizovat rychlost provádění, obsazení paměti, spotřebu energie, přenositelnost do jiných architektur nebo čas kompilace.
Křížová kompilace označuje řetězce kompilace schopné překládat zdrojový kód do objektového kódu, jehož architektura procesoru se liší od architektury, kde se kompilace provádí. Tyto řetězce se používají hlavně v průmyslových IT a ve vestavěných systémech .
Někteří překladači překládají zdrojový jazyk do jazyka virtuálního stroje (známého jako mezilehlý jazyk), to znamená do kódu (obecně binárního) prováděného virtuálním strojem : program emulující hlavní funkce počítače. O těchto jazycích se říká, že jsou částečně kompilované. Portování programu tedy vyžaduje pouze portování virtuálního stroje, kterým bude ve skutečnosti buď tlumočník, nebo druhý překladač (u překladačů s více cíli). Překladače tedy překládají Pascal do P-kódu, Modula 2 do M-kódu, Simula do S-kódu nebo nověji Java kód do Java bytecode (objektový kód).
Krátký program ve Scale.
Výsledný bajtový kód Java, spustitelný na virtuálním stroji.
Když je kompilace založena na bajtovém kódu, mluvíme o kompilaci za běhu . Potom používáme virtuální stroje, jako je virtuální stroj Java, se kterým můžeme pozoruhodně kompilovat Scalu . V některých jazycích je možné použít knihovnu umožňující on-the-fly kompilaci kódu zadaného uživatelem, například v C s libtcc.
Ostatní překladači překládají kód z jednoho programovacího jazyka do druhého. Říká se jim transcompilers , nebo dokonce anglicismus, transportéry nebo transpilátory. Například software LaTeX umožňuje ze zdrojového kódu v LaTeXu získat soubor ve formátu PDF (například příkazem pdflatex pod Ubuntu ) nebo HTML . Dalším příkladem je knihovna LLVM, která pomáhá vytvářet kompilátory a společnost AMD ji také používá k vývoji „HIP“, překladače kódu CUDA (specifický jazyk NVIDIA a široce používaný) za účelem jeho spuštění na grafických procesorech AMD.
Zdrojový kód.
Kód získaný po kompilaci.
Náhled dokumentu PDF.
Někteří překladači překládají zdrojový program (zadaný uživatelem), inkrementálně nebo interaktivně, do strojového kódu. Jako příklad můžeme uvést některé implementace Common Lisp (například SBCL (en) ).