Sémantika programovacích jazykov. Veľká encyklopédia ropy a zemného plynu

  • 18.06.2019

Doteraz sme hovorili, že program napísaný v jazyku vysokej úrovne by sa mal pred spustením skompilovať, teda preložiť do strojového jazyka pozostávajúceho z dvoch znakov zodpovedajúcich dvom stabilným stavom. Kompilátor Je to aj počítačový program, ktorého vstupom je súbor so zdrojovým textom napísaný v jazyku vysokej úrovne. Tento súbor sa nazýva v mnohých operačných systémoch zdrojový modul(zdrojový modul)... Kompilátor preloží program do strojového jazyka a zapíše ho do iného súboru tzv objektový modul(modul objektu).

V najjednoduchších prípadoch je možné obsah objektového modulu načítať do pamäte RAM a spustiť. Ale častejšie musí byť aj objektový modul zariadiť (odkaz) s inými objektovými modulmi, ktoré obsahujú doplnkové programové moduly, systémové funkcie, servisné informácie a ďalšie údaje potrebné na vykonávanie programu.

Linkovanie sa vykonáva špeciálnym programom, tzv "linker" (linker) alebo editor odkazov. Súbory s objektovými modulmi sa privádzajú na jeho vstup a výstup je spustiteľný modul (spustiteľný modul)- súbor s úplne pripraveným programom na spustenie. Tento súbor sa načíta do pamäte RAM a spustí sa.

Kompilácia a prepojenie sú často kombinované v jednom kroku. Na tento účel dostane kompilátor špeciálnu inštrukciu a ihneď po svojej práci zavolá samotný linker. Programátorovi sa to všetko zdá byť jediným procesom, iba na obrazovke sa zobrazujú správy o konci kompilácie a začiatku prepojenia.

Všetko popísané vyššie je typické pre kompilované programovacie jazyky. Ďalšia trieda jazykov, ktoré tvoria interpretované programovacie jazyky, ktoré nevyžadujú kompiláciu a prepojenie. Sú to tiež jazyky na vysokej úrovni, takže programy v nich napísané sa často nazývajú skripty (skript) alebo scenárov vyžadujú preklad do strojového jazyka. Na tento účel a operátor tlmočník zaznamenané v programe. Na rozdiel od kompilátora, tlmočnícky program neprekladá celý text do strojového jazyka, ale každý operátor samostatne a okamžite vykoná výsledný strojový kód.

Interpretácia programu je pomalšia ako spustenie spustiteľného súboru, pretože každý príkaz sa najskôr skonvertuje na strojový kód. Okrem toho sa počas interpretačného procesu môžu neočakávane vyskytnúť chyby, pretože zdrojový text nie je vopred skenovaný pri hľadaní chýb.

Interpretované jazyky sú však rozšírené kvôli pohodlnosti vytvárania programov s nimi. Program je možné napísať a spustiť okamžite bez predbežných transformácií. Ak sa práca programu javí ako neuspokojivá, potom je možné zmeniť jeho text a okamžite spustiť program znova bez akejkoľvek rekompilácie.

V modernom programovaní sa rozdiel medzi kompilovanými a interpretovanými jazykmi stiera. Toto zlúčenie prebieha dvoma spôsobmi. Na jednej strane sú kompilátory vytvorené pre interpretované jazyky. Klasický tlmočený jazyk bol vždy jazykom ZÁKLADNÉ, ale teraz bolo preň napísaných veľa kompilátorov. Programátor má na výber. Program napísaný v ZÁKLADNÉ, môže byť interpretovaný a okamžite spustený, alebo môže byť predkompilovaný do spustiteľného modulu a spustený v inom, vhodnejšom čase.

Na druhej strane sa tlmočníci naučili ukladať strojový kód už interpretovaných a vykonaných príkazov. Keď sa tieto príkazy vykonávajú opakovane, napríklad v slučkách, tlmočník používa hotové strojové inštrukcie, čo výrazne urýchľuje prácu. Takíto tlmočníci sú tzv JIT tlmočníkov (Práve včas)... Pracujú oveľa rýchlejšie ako klasickí tlmočníci, a preto sú čoraz rozšírenejšie.

Vo všeobecnosti je možné zostaviť a interpretovať akýkoľvek jazyk, takže toto rozdelenie sa vzťahuje na prax používania jazyka a nie je jeho vlastnosťou. V prípade mnohých jazykov však existuje rozdiel vo výkone medzi kompilovanými a interpretovanými implementáciami.

Veľký počet jazykov, vrátane BASIC, Lisp, Pascal a Python, má obe implementácie. Java používa kompiláciu JIT na generovanie strojového kódu, hoci je spočiatku preložená do interpretovanej podoby. Jazyky Microsoft .NET Framework ​​sú kompilované do Common Intermediate Language (CIL), ktorý je kompilovaný do natívneho kódu za behu. Väčšina implementácií Lisp vám umožňuje kombinovať oba druhy kódu.

História

V prvých rokoch programovania boli jazyky silne ovplyvnené výberom spôsobu vykonávania. Napríklad sa vyžadujú kompilované jazyky špecifikujúce typ údajov premennej v čase jej popisu alebo prvého použitia. Zatiaľ čo tlmočné jazyky vďaka svojej dynamickej povahe umožnili opustiť túto požiadavku, čo poskytlo väčšiu flexibilitu a zrýchlenie vývoja.

Pôvodne interpretované jazyky boli prevedené na strojový kód riadok po riadku, to znamená, že každý logický riadok bol zostavený tesne pred spustením. Výsledkom je, že každá inštrukcia uzavretá v tele cyklu a vykonaná niekoľkokrát bola prekladateľom spracovaná rovnako veľakrát. Takéto účinky sú dnes zriedkavé. Väčšina interpretovaných jazykov je vopred preložená do strednej reprezentácie. Je to bytecode alebo vláknový kód. Je to súbor inštrukcií na volanie malých kúskov kódu nižšej úrovne, ekvivalentný niekoľkým inštrukciám assembleru alebo inštrukciám virtuálneho stroja. Tento kód už vykonáva tlmočník alebo virtuálny stroj.

Takúto schému používajú napríklad nasledujúce jazyky:

  • Ruby (používa abstraktnú reprezentáciu stromu syntaxe kódu)

Stredný kód je možné generovať buď explicitným kompilačným postupom pre celý projekt (Java), alebo implicitným prekladom vždy pred spustením programu (Perl, Ruby) a pri zmene zdrojového kódu (Python).

Výhody

Existuje množstvo funkcií, ktoré je oveľa jednoduchšie implementovať v tlmočníkovi ako v kompilátore:

  • pomocou dynamického rozsahu a uzáverov

Princípy a štýl programovania navyše často nevyžadujú vytváranie a popis špeciálnych konštruktov, ktoré zdobia program (manifesty, triedy, dátové typy). To vám umožňuje vyvíjať a testovať kód postupne, čo je vhodné ako pre písanie malých programov, tak aj pre izolovaný vývoj modulov pre komplexné systémy. Vďaka svojej všestrannosti sa dajú pohodlne použiť ako skriptovacie jazyky.

nevýhody

Hlavnou nevýhodou je nižší výkon v porovnaní s kompilovanými jazykmi, ktoré sú konvertované do strojového kódu. Preklad bajtkódu a kompilácia JIT tento problém úplne nerieši. Ďalšia vrstva tlmočníka alebo virtuálneho stroja spomaľuje vykonávanie programu a môže vyžadovať viac zdrojov.

Kvôli chýbajúcej kompilácii celého projektu je možné väčšinu chýb zachytiť iba za behu. Výsledkom je, že v priemere by sa mal interpretovaný kód testovať dôkladnejšie ako kompilovaný kód, prísnejšie dodržiavať konvencie pre návrh programu a používať ďalšie analyzátory kvality kódu. Posledná nevýhoda nie je príliš výrazná, pretože pri serióznom vývoji v kompilovaných jazykoch je použitie týchto nástrojov tiež nevyhnutné.

Oblasti použitia

Eliminácia fázy kompilácie umožňuje rýchlejší vývoj programov, preto sa pri písaní zložitých jednorazových programov (napríklad na vykonanie jednorazového výpočtu) používajú interpretované jazyky.

Príklad


Nadácia Wikimedia. 2010.

Pozrite si, čo je „Interpretovaný programovací jazyk“ v iných slovníkoch:

    Vyvinutý spoločnosťou Sun Microsistems Corporation, multiplatformový, interpretovaný, objektovo orientovaný programovací jazyk používaný na vytváranie špičkových aplikácií webového prehliadača ... ... Finančná slovná zásoba

    Ruby Semantics: multiparadigm Typ prevedenia: tlmočník Rok výroby: 1995 Autor: Yukihiro Matsumoto Posledná verzia: 1.9.1 ... Wikipedia

    Programovací jazyk je formálny znakový systém na písanie počítačových programov. Programovací jazyk definuje súbor lexikálnych, syntaktických a sémantických pravidiel, ktoré definujú vzhľad programu a akcie, ... ... Wikipedia

    Tento výraz má iné významy, pozri B. Tento výraz má iné významy, pozri BI (významy). B Jazyková trieda: procedurálna Druh prevedenia: tlmočená Zavedené v: 1969 A ... Wikipedia

    Tento výraz má iné významy, pozri Dialekt (významy). Dialect Typ prevedenia: interpretované Autor(i): George Hart Dialektový interpretovaný programovací jazyk vytvorený Georgeom Hartom ako súčasť projektu inštitútu na ... Wikipedia Wikipedia

    ABC Jazyková trieda: imperatívny, procedurálny, štruktúrovaný Typ prevedenia: tlmočený, zostavený Rok zavedenia: 1987 Autor: Leo Geurts, Lambert Meertens (... Wikipedia

Prednáška 1- Programovacie jazyky. Vizuálny základ

(Z Wikipédie, voľnej encyklopédie) Programovací jazyk- formálny ikonický systém na popis algoritmy vo forme, ktorá je pre interpreta vhodná (napr. počítač). Programovací jazyk definuje množinu lexikálny,syntaktický a sémantický pravidlá používané pri zostavovaní počítačový program... Dovoľuje programátor presne určiť, na aké udalosti bude počítač reagovať, ako sa budú ukladať a prenášať údajov, ako aj to, aké akcie by sa mali s týmito údajmi vykonať za rôznych okolností. Od stvorenia prvých programovateľných strojov ľudstvo vynašlo už viac ako dva a pol tisíca programovacích jazykov. Zoznam programovacích jazykov(Angličtina)). Každý rok sa ich počet dopĺňa o nové. Niektoré jazyky pozná len malý počet ich vlastných vývojárov, iné sú známe miliónom ľudí. Profesionálni programátori niekedy vo svojej práci používajú viac ako tucet rôznych programovacích jazykov. Tvorcovia jazykov majú rôzne interpretácie tohto konceptu programovací jazyk... Medzi bežné miesta, ktoré väčšina vývojárov uznáva, patria:

    Funkcia: programovací jazyk určený na písanie počítačových programov, ktoré sa používajú na prenos do počítača inštrukcie o realizácii toho či onoho výpočtový proces a riadenie jednotlivca zariadení.

    Úloha: programovací jazyk je odlišný od prirodzené jazykyčo sa má prenášať tímov a údaje z osoby do počítača, pričom na komunikáciu sa používajú prirodzené jazyky z ľudí medzi sebou. V zásade je možné definíciu „programovacích jazykov“ zovšeobecniť – je to spôsob prenosu príkazov, príkazov, jasný návod na činnosť; pričom ľudské jazyky slúžia aj na výmenu informácií.

    prevedenie: programovací jazyk môže používať špeciálne konštrukcie na definovanie a manipuláciu dátové štruktúry a kontrola výpočtového procesu.

Vlastnosti programovacích jazykov

Každý programovací jazyk môže byť reprezentovaný ako súbor formálnych špecifikácií, ktoré ho definujú. syntax a sémantika Tieto špecifikácie zvyčajne obsahujú popisy:

    Typy a dátové štruktúry

    Operačná sémantika (algoritmus na výpočet jazykových konštruktov)

    Sémantické jazykové konštrukty

    Knižnice primitív (napríklad I/O inštrukcie)

    Filozofia účelu a možností jazyka

Pre mnohé široko používané programovacie jazyky boli zriadené Medzinárodné výbory pre normalizáciu, ktoré pravidelne aktualizujú a zverejňujú špecifikácie a formálne definície príslušného jazyka. V rámci takýchto komisií pokračuje vývoj a modernizácia programovacích jazykov a riešia sa otázky rozširovania či podpory existujúcich a nových jazykových konštrukcií.

Typy údajov

Vo vnútornej reprezentácii sú všetky údaje v moderných digitálnych počítačoch uložené jednoducho ako nuly a jednotky ( binárne). Údaje, ktoré predstavujú informácie zo skutočného sveta (mená, bankové účty, merania atď.), sú binárne údaje nízkej úrovne, ktoré programovacie jazyky prekladajú do týchto vysokoúrovňových konceptov.

Špeciálny systém, podľa ktorého sú údaje v programe organizované, je typový systém programovací jazyk; vývoj a štúdium typových systémov je známe ako teória typu... Jazyky možno klasifikovať ako systémy staticky typizované a jazyky s dynamické písanie ... Staticky písané jazyky je možné ďalej rozdeliť na jazyky s povinné vyhlásenie kde každá deklarácia premennej a funkcie má povinnú deklaráciu typu a jazyky s odvodené typy... Niekedy sa nazývajú dynamicky písané jazyky latentne napísané .

Dátové štruktúry

Typové systémy v jazykoch vysokej úrovne umožňujú definíciu zložitých, zložených typov, tzv dátové štruktúry... Typicky sú štruktúrované dátové typy tvorené ako karteziánsky súčin základné (atómové) typy a predtým definované kompozitné typy. Základné dátové štruktúry (zoznamy, fronty, hašovacie tabuľky, binárne stromy a páry) sú vo vyšších jazykoch často reprezentované špeciálnou syntaxou. Takéto údaje sú štruktúrované automaticky.

Kompilované a interpretované jazyky

Programovacie jazyky sú rozdelené do dvoch tried - skompilovaný a vykladané... Program v kompilovanom jazyku pomocou špeciálneho programu kompilátor transformuje ( zostavuje) do sady inštrukcií pre daný typ procesora (strojového kódu) a následne zapísaných do spustiteľný súbor, ktorý je možné spustiť ako samostatný program. Inými slovami, kompilátor preloží program z jazyka vysokej úrovne do jazyka nízkej úrovne, ktorému procesor rozumie. Ak je program napísaný v interpretovanom jazyku, potom tlmočník priamo vykonáva ( vykladá) jeho text bez predbežného prekladu. V tomto prípade zostáva program v pôvodnom jazyku a nemožno ho spustiť bez tlmočníka. Môžeme povedať, že procesor počítača je interpretom strojového kódu. Skrátka, kompilátor preloží program do strojového jazyka naraz a celý, čím vytvorí samostatný program a tlmočník preloží do strojového jazyka priamo počas vykonávania programu. Rozdelenie na kompilované a interpretované jazyky je trochu ľubovoľné. Takže pre akýkoľvek tradične zostavovaný jazyk ako napr Pascal, môžete napísať tlmočníka. Navyše väčšina moderných „čistých“ tlmočníkov nevykonáva priamo jazykové konštrukty, ale kompiluje ich do nejakej strednej reprezentácie na vysokej úrovni (napríklad s variabilným dereferencovaním a makro expanziou). Môžete vytvoriť kompilátor pre akýkoľvek interpretovaný jazyk - napríklad natívne interpretovaný jazyk Lisp je možné zostaviť bez akýchkoľvek obmedzení. Kód vytvorený za behu môže byť tiež dynamicky kompilovaný počas behu. Kompilované programy spravidla bežia rýchlejšie a na spustenie nevyžadujú ďalšie programy, pretože už boli preložené do strojového jazyka. Zároveň pri každej zmene textu programu je potrebné ho prekompilovať, čo spôsobuje ťažkosti pri vývoji. Navyše, skompilovaný program môže bežať len na rovnakom type počítačov a spravidla pod tým istým operačným systémom, pre ktorý bol kompilátor navrhnutý. Na vytvorenie spustiteľného súboru pre iný typ počítača je potrebná nová kompilácia. Interpretované jazyky majú niektoré špecifické dodatočné schopnosti (pozri vyššie), navyše programy v nich možno spustiť ihneď po úprave, čo uľahčuje vývoj. Interpretovaný jazykový program možno často spustiť na rôznych typoch strojov a operačných systémov bez ďalšieho úsilia. Interpretované programy sa však vykonávajú výrazne pomalšie ako kompilované programy a navyše ich nemožno vykonávať bez dodatočného programu na prekladanie. Niektoré jazyky napr Java a C # sú medzi kompilovaným a interpretovaným. Program totiž nie je skompilovaný do strojového jazyka, ale do nízkoúrovňového strojovo nezávislého kódu, bytecode... Ďalej sa vykoná bytecode virtuálny prístroj... Na vykonanie bajtkódu sa zvyčajne používa interpretácia, aj keď niektoré jej časti na zrýchlenie programu je možné preložiť do strojového kódu priamo počas vykonávania programu pomocou technológie kompilácie Just-in-time. JIT). V prípade jazyka Java je bajtový kód vykonávaný virtuálnym strojom Java ( JVM), pre C # - Common Language Runtime... Tento prístup vám v istom zmysle umožňuje využívať výhody interpretov aj kompilátorov. Treba uviesť aj pôvodný jazyk. Forth, ktorý je akoby interpretovaný aj zostavený.

programovací jazyk možno tiež považovať za strojový kód nejakého abstraktného počítača, ktorý sa líši od skutočných procesorov. V takýchto prípadoch budeme hovoriť o abstraktných alebo virtuálnych strojoch.

Cieľom kompilácie je umožniť skutočnému počítaču spustiť kód napísaný pre abstraktný stroj. Kompilácia je však len jednou z dvoch základných technológií používaných na dosiahnutie nášho cieľa.

Základné schémy

Namiesto kompilácie programu ho môžete interpretovať. Obrázok nižšie ilustruje rozdiel v prístupoch, pričom ignoruje úlohu vstupov.


Ryža. 3.6.

Kompilátor aj interpret sú programy, ktoré berú ako vstup programy napísané v programovacom jazyku. Kompilátor preloží do neho prenesený program do cieľovej podoby - strojového kódu, ktorý je už možné priamo spustiť na počítači, čím vytvorí výstupné výsledky výpočtov. Spracovanie rovnakého zdrojového programu tlmočníkom nevytvorí cieľový program, ale priamo ho vykoná, čím sa získajú výstupné výsledky.

Tlmočník musí byť schopný určiť účinok vykonania každej konštrukcie v programovacom jazyku. Ako príklad toho, ako tlmočník vykonáva svoju úlohu, uvažujme interpretáciu zadania x: = x +1. Interpret musí viesť tabuľku všetkých použitých premenných a ich priradených hodnôt. Vypočíta novú hodnotu x pridaním 1 k starej hodnote uloženej v tabuľke a potom vykoná priradenie, pričom nahradí starú hodnotu x hodnotou vypočítaného výrazu.

Kompilátor vygeneruje strojový kód, ktorý vytvorí rovnaký efekt pomocou počítačových inštrukcií a adries pamäte (namiesto štruktúry vyššej úrovne, ako je napríklad tabuľka).

V paralelnom cvičení pre malý jazyk budete musieť napísať kompilátor a tlmočník pomocou týchto myšlienok.

Ak považujeme programovací jazyk za strojový kód pre abstraktný stroj, môžeme povedať, že tlmočník je program, ktorý simuluje výpočty na tomto stroji. Pamäť stroja je v tomto prípade tiež abstraktná a predstavuje dátové štruktúry vo forme tabuliek interpretu "premenné - hodnoty".

Na nasledujúcom obrázku sú procesy zostavovania a interpretácie doplnené o zadávanie údajov:


Ryža. 3.7.

Obrázok ukazuje ďalší rozdiel medzi kompilátorom a tlmočníkom. Interpret má dva zdroje vstupu – pôvodný program a vstupné dáta; a do kompilátora sa dostane iba program. V nasledujúcej diskusii dáme tomuto rozlíšeniu matematickú formu.

Kompilovať alebo tlmočiť? Tento problém je predmetom rozsiahlej úvahy v informatike. Čo je lepšie: priamo spracovať prvotné informácie tak, ako sú, alebo ich predbežne uviesť do vhodnejšej podoby? Táto otázka vyvstáva nielen pri spracovaní programov, stretneme sa s ňou aj pri štúdiu algoritmov.

Kompilátori a interpreti majú svoje opodstatnenie. Možné sú rôzne kritériá. Z hľadiska výkonu – času vykonávania programu – víťazia kompilátory.

  • Výstup kompilátora je strojový kód, ktorý je vykonávaný priamo počítačom. Okrem toho pri generovaní tohto kódu môže kompilátor použiť optimalizácie na zlepšenie efektívnosti kódu.
  • Interpretácia kódu vyžaduje predbežné spracovanie každého príkazu. V dôsledku toho je interpretácia programu rádovo pomalšia v porovnaní s prácou programu vytvoreného kompilátorom.

Všetko sa zmení, ak si ako kritérium zvolíte pohodlie a rýchlosť vývoja. Kompilátor stojí medzi vami a implementáciou vášho posledného nápadu: predtým, ako uvidíte výsledky poslednej zmeny v programe, musíte počkať na výsledok kompilácie (a prepojenia, o ktorom bude reč nižšie). Po interpretácii sa okamžite spustí vykonávanie.

V moderných vývojových prostrediach nie je táto nevýhoda kompilácie taká kritická kvôli použitej technológii. "prírastková kompilácia" keď, keď vykonáte zmenu, skompilujú sa iba tie časti programu, ktorých sa zmena týka. Na konci tejto prednášky sa pozrieme na to, ako táto technológia funguje v EiffelStudio.

Ďalším kritériom, podľa ktorého je kompilácia opäť preferovaná, je spoľahlivosť programu. Kompilátory nielen prekladajú program, ale vykonávajú rôzne kontroly počas kompilácie, napríklad kontrolu typu staticky písané jazyky... Mnoho chýb je teda eliminovaných už vo fáze kompilácie, zatiaľ čo chyby pre režim interpretácie sa zisťujú počas vykonávania v jednej z pracovných relácií.

V zásade je tlmočník schopný vykonať aj niektoré kontroly pred spustením programu. V skutočnosti sa nepoužívajú čisté tlmočníky, vždy ide o zmes kompilácie a interpretácie.

Kombinácia kompilácie a interpretácie

Čistá kompilácia a čisté interpretačné schémy sú okrajové možnosti: väčšina praktických riešení je kombináciou. To isté platí pre proces kompilácie v EiffelStudio, ktorému sa budeme venovať neskôr v tejto kapitole.

Všimnite si, že 100% interpretačná schéma nemá zmysel: zakaždým, keď tlmočník vykoná iný operátor, napríklad operátor slučky, musel by sa mnohokrát vrátiť k skutočnej sekvencii znakov a analyzovať ju. Akékoľvek realistické riešenie by nemohlo súhlasiť s takýmto nerozumným plytvaním zdrojmi. Takže vlastne aj interpret začína transformáciou vstupu do formy, ktorá sa dá interpretovať, napríklad zostavením abstraktného stromu syntaxe. Počas tohto procesu, ako bolo uvedené, je možná kontrola typu. Takže aj keď sa dočítate, že sa používa jazykový tlmočník, predpokladá sa čiastočná kompilácia.

Kombinácia interpretácie a kompilácie výrazne presahuje túto základnú myšlienku. Výstup kompilátora by nemal byť priamy strojový kód, môže byť predmetom ďalšieho spracovania.


Ryža. 3.8.

Zmiešaná stratégia predpokladá, že kompilátor generuje kód v stredný jazyk, ktorému rozumie nejaký virtuálny stroj - VM na obrázku. Tento prístup spája výhody kompilácie a interpretácie. Vďaka starostlivo navrhnutému virtuálnemu stroju je možné získať:

  • prenosnosť, pretože kód VM nezávisí od špecifík fyzických procesorov;
  • zvýšenie efektívnosti, od r medzikódľahko interpretovateľné.

Virtuálne stroje, bytecode a kompilátory JIT (Just In Time).

Implementácia moderných jazykov - Java, C #, ďalšie jazyky .Net - je založená na zmiešanom riešení. Medzikód pre Java sa nazýva bytecode. Tento výraz odráža skutočnosť, že virtuálny stroj používa kompaktné príkazy, podobné príkazom skutočného procesora, kde každý príkaz obsahuje kód príkazu – zvyčajne jeden bajt – nasledovaný 0, 1 alebo 2 argumentmi príkazu.

Alternatívou k bajtkódu by mohol byť virtuálny stroj, ktorý priamo pracuje s dátovými štruktúrami, napríklad s abstraktným syntaktickým stromom reprezentujúcim štruktúru programu as hašovacími tabuľkami na ukladanie vlastností premenných. Ale bajtkód poskytuje lepšiu efektivitu behu, a to ako v čase, tak v pamäti.

Technika dvojstupňovej kompilácie bola použitá už v sedemdesiatych rokoch pri implementácii kompilátora z jazyka Pascal. Znovuzrodenie sa dočkalo s rozšírením internetu, pretože sa dobre hodilo na lokálne spúšťanie webovými klientmi. Dodávatelia apletov – malých programov – by ich mohli skompilovať do bajtového kódu a dodať ich v tejto forme. Ďalšou výhodou kompaktnosti bola prenosnosť kódu, pretože inak by bolo potrebné vytvoriť strojový kód pre všetko možné cieľová platforma.

Používatelia potrebujú na spustenie apletu iba interpret bajtového kódu. Nemusia ani vedieť, že takýto tlmočník existuje, ak je zabudovaný do ich webového prehliadača. Pretože tento prístup predstavuje potenciálne bezpečnostné riziká – nečestné alebo nesprávne aplety môžu poškodiť váš počítač – z tohto dôvodu je pre aplety potrebný tlmočník. ktorý bude prísne kontrolovať operácie povolené pre applety.

Doručovanie softvéru prostredníctvom apletov malo určitý úspech, ale nestalo sa hlavným spôsobom distribuovaného softvéru, ako sa očakávalo, keď bola predstavená Java. Čiastočne je to spôsobené obavami o bezpečnosť, ale hlavným dôvodom je strata účinnosti v dôsledku výkladu. Najúspešnejšie aplety sú malé programy určené na spustenie na webovej stránke a obsahujú vizuálny komponent, ktorý výrazne nestráca čas.

Na zlepšenie efektívnosti času vykonávania bajtkódu sa používajú kompilátory JIT (Just In Time), nazývané jittery, ktoré sa kompilujú na požiadanie. Hlavnou myšlienkou je, že strojový kód pre určitý modul vzniká „za behu“, v momente, keď je prvýkrát vyzvaný na vykonanie (nepleťte si milovníka jazzu – jitterbug, s chybami takéhoto kompilátora – jitter bug ). Urobme príslušné doplnky k predchádzajúcemu obrázku, ktorý teraz vyzerá takto:


Ryža. 3.9.

Zvyčajne, ako je znázornené na obrázku, spolu s priebežnou kompiláciou (jiting) existuje aj možnosť interpretácie bajtového kódu. Priebežná kompilácia sa zvyčajne vyskytuje pri prvom použití modulu (metódy alebo celej triedy), takže bude potrebná iba pre kód, ktorý sa v danom spustení skutočne používa. V porovnaní s tradičným kompilátorom, ktorý skompiluje celý program, vám tento prístup umožňuje vytvárať kompaktnejší kód, skracuje čas kompilácie, ale čo je dôležitejšie, robí kompiláciu súčasťou procesu vykonávania. To je vážna nevýhoda, pretože náklady na kompiláciu sa pripočítavajú k runtime, takže samotný runtime sa stáva menej predvídateľným.

Na prvý pohľad sa zdá, že s týmto prístupom sa neoplatí robiť kontrolu typu a iné kontroly, pretože kto chce dostávať správy o porušení za behu konzistencia typu? To by nás dynamicky priviedlo späť k problémom písané jazyky... Samozrejme, boli by sme radi, keby sa všetky potrebné kontroly vykonali v prvom kroku kompilácie pri vytváraní bajtkódu, aby bol akýkoľvek kód odovzdaný do jitteru bezpečný. Bohužiaľ, tieto upokojujúce predpoklady sú nereálne v distribuovanom prostredí, kde opäť vznikajú bezpečnostné problémy. Ak si stiahnete bajtový kód zo stránky, viete, či prešiel overením? Vo všeobecnosti nie. Potom sa však porušenia typu môžu stať nielen príčinou narušenia spoľahlivosti a abnormálneho ukončenia programu, všetko môže byť oveľa horšie: v dôsledku útoku je možné narušenie bezpečnosti.

Z pohľadu bezpečnostných expertov sú narušenia bezpečnosti horšie ako abnormálne ukončenia: v prípade nehody sa všetko zastaví, v prípade narušenia bezpečnosti môže program bezpečne pokračovať vo svojej práci a dokonca poskytnúť správne výsledky, ale dôverné informácie, ktoré sú hodnotnejšie ako dosiahnuté výsledky sa môžu stratiť.

V dôsledku toho v praxi zahŕňa priebežná kompilácia aj tak kontrolu konzistencia typu... Strata výkonu môže byť stále prijateľná, pretože typový systém virtuálneho stroja s bajtovým kódom je oveľa jednoduchší, zvyčajne ako typový systém pôvodného programu.

Stratégia kompilácie v EiffelStudio zahŕňa aj bytecode, no ako uvidíme, používa rôzne spôsoby kombinovania interpretácie a kompilácie.

V tomto cykle chcem upriamiť vašu pozornosť na kľúčové princípy programovania, ktoré ovplyvňujú všetko, čo robíme, no ktorým sa málokedy priamo venujeme, a preto im úplne nerozumieme. Témou dnešného článku sú zostavené a interpretované jazyky.

Ako vývojári sme často konfrontovaní s pojmami ako kompilátor a tlmočník, no zisťujem, že mnohí celkom nerozumejú, čo znamenajú. Kompilácia a interpretácia sú medzitým základom toho, ako fungujú všetky programovacie jazyky. Poďme sa pozrieť na to, ako tieto koncepty v skutočnosti fungujú.

Úvod

Spoliehame sa na nástroje, ako je kompilácia a interpretácia, aby sme transformovali náš kód do formy, ktorej počítač rozumie. Kód môže byť spustený natívne, v operačnom systéme po konverzii na strojový kód (kompiláciou), alebo môže byť riadok po riadku spustený iným programom, ktorý to robí namiesto OS (prekladač).

Kompilovaný jazyk je taký, že program, keď je kompilovaný, obsahuje inštrukcie cieľového počítača; tento strojový kód je pre ľudí nezrozumiteľný. Interpretovaný jazyk je jazyk, v ktorom inštrukcie nie sú vykonávané cieľovým strojom, ale sú čítané a vykonávané iným programom (ktorý je zvyčajne napísaný v jazyku cieľového stroja). Kompilácia aj interpretácia majú svoje klady a zápory a o tom budeme diskutovať.

Než budeme pokračovať, stojí za zmienku, že mnoho programovacích jazykov má kompilované aj interpretované verzie, takže je ťažké ich klasifikovať. Aby však veci zostali jednoduché, v nasledujúcom texte oddelím kompilované a interpretované jazyky.

Kompilované jazyky

Hlavnou výhodou kompilovaných jazykov je rýchlosť vykonávania. Keďže sú konvertované do strojového kódu, sú oveľa rýchlejšie a efektívnejšie ako interpretované, najmä ak vezmeme do úvahy zložitosť príkazov niektorých moderných skriptovacích interpretovaných jazykov.

Nízkoúrovňové jazyky majú tendenciu byť kompilované, pretože efektivita je zvyčajne uprednostňovaná pred multiplatformnými. Kompilované jazyky navyše dávajú vývojárom oveľa väčšiu kontrolu nad hardvérom, ako je napríklad správa pamäte a využitia procesora. Príkladmi kompilovaných jazykov sú Erlang a modernejšie jazyky ako a.

Problémy kompilovaných jazykov sú vo všeobecnosti zrejmé. Ak chcete spustiť program napísaný v kompilovanom jazyku, musíte ho najskôr skompilovať. Ide nielen o krok navyše, ale aj o značnú komplikáciu ladenia, pretože na otestovanie akejkoľvek zmeny je potrebné program skompilovať znova. Okrem toho sú kompilované jazyky závislé od platformy, pretože strojový kód závisí od stroja, na ktorom je program kompilovaný a spustený.

Tlmené jazyky

Na rozdiel od kompilovaných jazykov, interpretované jazyky nepotrebujú strojový kód na spustenie programu; namiesto toho budú tlmočníci vykonávať program riadok po riadku. V minulosti bol proces tlmočenia veľmi zdĺhavý, ale s príchodom technológií, ako je napríklad, sa priepasť medzi kompilovanými a interpretovanými jazykmi zmenšuje. Príkladmi interpretovaných jazykov sú a. Tu sú niektoré z konceptov, ktoré uľahčujú interpretované jazyky:

  • Nezávislosť na platforme;
  • Menšie spustiteľné súbory:

Hlavnou nevýhodou tlmočených jazykov je ich nízka rýchlosť vykonávania. Kompilácia JIT však môže urýchliť proces prekladom často používaných sekvencií inštrukcií do strojového kódu.

Bonus: jazyky bytecode

Bytecode jazyky sú jazyky, ktoré používajú kompiláciu aj interpretáciu na vykonávanie kódu. Java a framework .NET sú typickými príkladmi jazykov bajtkódu. V skutočnosti je Java Virtual Machine (JVM) taký populárny virtuálny stroj na interpretáciu bajtového kódu, že spúšťa implementácie viacerých jazykov. Mimochodom, nedávno bude nová verzia Javy podporovať aj statickú kompiláciu.

V bajtkódovom jazyku je program najprv skompilovaný z človeka čitateľného jazyka do bajtového kódu. Bytecode je súbor inštrukcií navrhnutých tak, aby ich interpret mohol efektívne vykonávať a pozostával z kompaktných číselných kódov, konštánt a pamäťových odkazov. Od tohto momentu sa bajtkód prenesie do virtuálneho stroja, ktorý potom interpretuje kód rovnakým spôsobom ako bežný interpret.

Pri kompilácii kódu do bajtkódu dochádza k oneskoreniu, ale ďalšia rýchlosť vykonávania sa výrazne zvyšuje vďaka optimalizácii bajtkódu. Okrem toho sú jazyky bajtkódu nezávislé na platforme, pričom prekonávajú interpretované jazyky. K dispozícii je pre nich aj kompilácia JIT.

Záver

Mnoho jazykov má v súčasnosti skompilované aj interpretované implementácie, vďaka čomu je rozdiel medzi nimi nulový. Každý typ vykonávania kódu má výhody a nevýhody.

Stručne povedané, kompilované jazyky sú najefektívnejšie, pretože sa vykonávajú ako strojový kód a umožňujú použitie hardvéru systému. To však zavádza ďalšie obmedzenia kódovania a robí ho špecifickým pre platformu. Interpretované jazyky sú nezávislé na platforme a umožňujú techniky dynamického programovania, ako je metaprogramovanie. Z hľadiska rýchlosti vykonávania sú však výrazne horšie ako kompilované jazyky.

Na druhej strane jazyky bajtkódu sa snažia využiť prednosti oboch druhov jazykov a robia to dobre.