Fordítóprogram
A fordítóprogram (angolul compiler) olyan számítógépes program, amely valamely programozási nyelven írt programot képes egy másik nyelv szabályaira lefordítani, például gépi kódra, köztes kódra vagy egy másik programozási nyelv kódjára. A fordítóprogram elnevezést első sorban olyan programokra használják, ahol a forráskód (source code) valamilyen magas szintű programozási nyelv (például C# vagy Java), a célnyelv pedig, amire a fordító lefordítja a programot, valamilyen alacsony szintű nyelv (pl. assembly vagy gépi kód), amelyek már futtatható kódok.
Sokféle különböző fordítóprogram létezik. Ha a lefordított program olyan számítógépen bír futni, aminek a CPU-ja vagy az operációs rendszere különbözik attól a számítógéptől, amin a fordítás végbement, akkor keresztirányú fordítóprogramról (cross compilerről) beszélünk. A bootstrap compiler olyan fordító, amit azon a nyelven írnak, amit le kíván fordítani. Azt a fordítót, ami alacsony szintű nyelvről magasabb szintű nyelvre fordít, kódvisszafejtő programnak (angolul decompiler) nevezik. Az a program, ami adott magas szintű programozási nyelvről egy másik magas szintű programozási nyelvre fordít, source-to-source compiler. Egy nyelv-újraíró olyan program, ami a kifejezések formáját nyelvváltoztatás nélkül hajtja végre. A fordító generátor compiler-compiler fogalom olyan programozó eszközt takar, amely elemzőt, értelmezőt vagy fordítót hoz létre a programozási nyelv és a gép formális leírása alapján.
Csoportosítás
szerkesztésA fordítandó programot forrásprogramnak (nyelvét forrásnyelvnek), a lefordított programot tárgyprogramnak (nyelvét tárgynyelvnek) nevezzük.
E szerint a fordítóprogramokat a következőképp csoportosíthatjuk:
- natív kódra fordítók
- több platformra fordítók
- magas szintű nyelvből egy másik magas szintű nyelvre
Kivitelezés
szerkesztésA fordítóprogram végrehajtja a formális átalakítást egy magas szintű forrásnyelvről egy alacsony szintű tárgynyelvre. A fordítókészlet meghatároz egy végponttól végpontba (end to end) megoldást, vagy kezelhet egy meghatározott részhalmazt, amely kapcsolódik más fordítási eszközökhöz pl. előfeldolgozókhoz (preprocessors), összeszerelőkhöz (assemblers), összekötőkhöz(linkers). A tervezési követelmények szigorúan meghatározott felületeket tartalmaznak mind a fordítóelemek mind pedig a támogató eszközök között.
Kezdetben a fordítók tervezésének megközelítését közvetlenül befolyásolták a feldolgozandó számítógépes nyelv összetettsége, a tervező személy(ek) tapasztalata és a rendelkezésre álló források. Az erőforrás-korlátozások szükségessé tették a forráskód többszöri áthaladását.
Egy viszonylag egyszerű nyelv fordítója, amelyet ember írt, lehet egyetlen monolitikus szoftver. Mivel azonban a forrásnyelv ettől bonyolultabbá válhat, a terv több egymástól függő fázisra bontható. Külön szakaszok biztosítják a tervezési fejlesztéseket, amelyek a fejlesztés a fordítási folyamat funkcióira összpontosítanak.
A fordítóprogramok két fázisban dolgozzák fel a kódot:
- az elsőben lefordítja a forráskódot egy közbeeső kódra (előrész)
- a második fázisban történik az úgynevezett fordítási eljárás. (hátrész)
Első fázis (Front End)
szerkesztésEzt a fázist három nagy fázisra lehet bontani: lexikális elemzésre, szintaktikai elemzésre és szemantikai elemzésre.
A front end a forráskódot elemzi a program belső reprezentációjának és az ún. közbenső reprezentációnak (intermediate representation, IR) felépítéséhez. Ezen felül kezeli a szimbólumtáblát, egy adatszerkezetet amely leképzi a forráskód minden szimbólumát a kapcsolódó információkkal mint például a hely, típus és hatókört (scope).
Lexikális elemzés
szerkesztésA forráskód tokenizálása, felbontása a szintaktikai elemzőnek értelmezhető szimbólumokká, azaz a nyers forrásszövegből kreál szimbólumsorozatot, általában operátorok, fenntartott szavak, azonosítók stb. formájában. A lexikai hibák általában elírásokból adódnak, ezeket legjobb tudásuk szerint elfedik az elemzők, sokszor kitalálva, mit is akarhatott írni a programozó.
Szintaktikai elemzés
szerkesztésA nagyrészt környezetfüggetlen nyelvtan alapján felépíti a szintaxisfát, az esetleges hibákat tudása szerint átugorva.
Főbb fajtái az LL és az LR elemzők.
Szemantikai elemzés
szerkesztésA dinamikus szemantika ellenőrzése történik ebben a szakaszban, típusellenőrzések, függvények paraméterszáma, típushelyessége, általában a programkód értelmessége. Míg a lexikális és a szintaktikus ellenőrzésre már igen jó automatizált eszközeink vannak, a szemantikus elemzést mindeddig nem sikerült általánosan és hatékonyan automatizálni.
Hátrész
szerkesztésItt történik a közbeeső kód lefordítása gépi kódra. Ez is több lépésből tevődik össze:
- optimizálás: opcionális, a közbeeső kód átalakítása kisebb és gyorsabb formába (a program kívülről látható működése ettől (többnyire) nem változik). Általában ezt már az assembly nyelvű kódon végzi a fordítóprogram.
- kódgenerálás: a gépi kód generálása. A mnemonikok egyszerű átfordítása gépi kóddá valamint a modulon belül feloldható hivatkozások feloldása, ugrási címkék kiszámítása.
Fordítóprogram vagy interpreter?
szerkesztésA magas szintű programozási nyelven megírt programot futtatáshoz fordítóprogrammal lefordítjuk gépi kódra, vagy interpreterrel interpretárjuk, vagyis értelmezzük. Az első esetben ún. object code keletkezik, amiből szerkesztéssel lehet futtatható programot készíteni. A második esetben általában nem keletkezik futtatható program, legfeljebb egy tömör, mindenféle felesleges résztől mentes közbülső kód (néha ún. bytecode), amit az interpreter második fázisa végrehajt.
Történet
szerkesztésA tudósok, matematikusok és mérnökök által kidolgozott elméleti számítási koncepciók képezték a digitális modern számítástechnika fejlesztésének alapját a második világháború idején. Az elsődleges bináris nyelvek azért fejlődtek ki, mert a digitális eszközök csak az egyeseket és a nullákat, valamint az alapjául szolgáló gépi architektúra áramkörmintáit értik meg. Az 1940-es évek végén assembly nyelveket hoztak létre, hogy a számítógépes architektúrák jobban kivitelezhetők legyenek. A korai számítógépek korlátozott memóriakapacitása komoly technikai kihívásokhoz vezetett az első fordító tervezésekor. Ezért a fordítási folyamatot több kisebb programra kellett felosztani. A felhasználói felületek programjai előállítják azokat az elemző termékeket, amelyeket a back end a célkód előállításához használnak. Ahogyan a számítógépes technológia több forrást biztosított, a fordítók jobban igazodhattak magához a fordítási folyamathoz.
A programozók számára általában hatékonyabb a magas szintű nyelv használata, így a magas szintű nyelvek fejlesztése a digitális számítógépek által kínált lehetőségekből fakad. A magas szintű nyelvek olyan formális nyelvek, amelyeket szintaxisuk és szemantikájuk szigorúan meghatároznak, és amelyek a magas szintű nyelvi architektúrát alkotják. Ezen formális nyelvek elemei a következők:
- ábécé, bármilyen véges szimbólumkészlet;
- karakterlánc, a szimbólumok véges sorozata;
- nyelv, bármilyen karakterlánckészlet ábécében.
A mondatokat egy nyelvben meghatározhatja egy nyelvtannak nevezett szabálykészlet.
A Backus–Naur-forma (BNF) leírja a nyelv „mondatainak” szintaxisát, és John Backus az Algol 60 szintaxisához használta. Az ötletek Noam Chomsky, nyelvész, kontextus nélküli nyelvtani fogalmaiból származnak. "A BNF és annak kiterjesztései sztenderd eszközökké váltak a programozási jelölések szintaxisának leírására, és sok esetben a fordítók részeit automatikusan generálják a BNF leírásból."
Az 1940-es években Konrad Zuse egy algoritmikus programozási nyelvet készített Plankalkül ("Plan Calculus") néven. Noha az 1970-es évekig nem valósult meg a megvalósítás, a későbbiekben az APL-ben látott koncepciókat mutatta be, amelyeket Ken Iverson tervezett az 1950-es évek végén.A z APL egy nyelv matematikai számításokhoz.
A magas szintű nyelvtervezés a digitális számítástechnika kialakulási éveiben hasznos programozási eszközöket nyújtott számos alkalmazáshoz:
- A mérnöki és tudományos alkalmazásokban használt FORTRAN (Formula Translation) tekinthető az első magas szintű nyelvnek.
- A COBOL (Common Business-Oriented Language) az A-0-ból és a FLOW-MATIC-ból alakult ki az üzleti alkalmazások domináns magas szintű nyelvévé.
- LISP (List Processor)szimbolikus számításhoz.
A fordítótechnika a magas szintű forrásprogram szigorúan meghatározott átalakításának szükségességéből fejlődött ki a digitális számítógép alacsony szintű célprogramjává. A fordítót előtérként lehet tekinteni a forráskód elemzésének kezelésére, és a back end az elemzés célkódba történő szintetizálására. A front end és a back end közötti optimalizálás hatékonyabb célkódot eredményezhet.
Korai mérföldkövek a fordító technológia fejlesztésében:
- 1952 - Alick Glennie által a Manchesteri Egyetemen a Manchester Mark I számítógéphez kidolgozott Autokód-fordítót tekintik sokan az első fordítónak.
- 1952 - Grace Hopper Remington Rand csapata az A-0 programozási nyelv fordítóját írta (és már a fordító kifejezést használta annak leírására), bár az A-0 fordító inkább betöltőként vagy összekötőként működött, mintsem úgy mint egy teljes fordító.
- 1954-1957 - John Backus vezetésével az IBM fejlesztette ki a FORTRAN-t, amelyet általában az első magas szintű nyelvként tartanak számon. 1957-ben befejezték a FORTRAN fordítót, amelyet úgy tekintenek, mint az első egyértelműen teljes fordító bevezetését.
- 1959 - Az adatrendszer-nyelvi konferencia (CODASYL) elindította a COBOL fejlesztését. A COBOL kialakítása az A-0 és a FLOW-MATIC rajzokra támaszkodott. Az 1960-as évek elején a COBOL-t több architektúrára állították össze.
- 1958-1962 - John McCarthy, a Stanford Egyetemen tervezte meg a LISP-t. A szimbólumfeldolgozó képességek hasznos funkciókat nyújtottak a mesterséges intelligencia kutatására. 1962-ben a LISP 1.5 kiadás néhány eszközt felsorolt: Stephen Russell és Daniel J. Edwards írta az interpretert, míg Tim Hart és Mike Levin a fordítót és az assemblert írta.
A korai operációs rendszereket és szoftvereket assembly nyelven írták. A 60-as években és a 70-es évek elején az erőforrások korlátozottsága miatt a magas szintű nyelvek használata a rendszerprogramozásban továbbra is vitatott volt. Számos kutatási és ipari erőfeszítés azonban elindította az elmozdulást a magas szintű rendszerek programozási nyelvei felé, például a BCPL, a BLISS, a B és a C.
BCPL-t (alapvető kombinált programozási nyelv), amelyet 1966-ban tervezett Martin Richards a Cambridge-i Egyetemen, eredetileg fordító író eszközként fejlesztették ki. Számos fordítót implementáltak, Richards könyve betekintést nyújt a nyelvbe és annak fordítójára. A BCPL nemcsak befolyásos rendszerprogramozási nyelv volt, amelyet továbbra is használnak a kutatásban, hanem alapot adott a B és a C nyelv megtervezéséhez is.
A BLISS-t (alapvető nyelv a rendszerszoftverek megvalósításához) a Digital Equipment Corporation (DEC) PDP-10 számítógép számára fejlesztették ki W. A. Wulf Carnegie Mellon Egyetem (CMU) kutatócsoportja. A CMU csapata egy évvel később, 1970-ben fejlesztette ki a BLISS-11 fordítót.
A Multics (Multiplexed Information and Computing Service), idő-megosztó operációs rendszer projekt, bevonta az MIT-t, a Bell Labs-t, a General Electric-t (később Honeywell), és Fernando Corbató vezette az MIT-ből. A Multics az IBM és az IBM User Group által kifejlesztett PL / I nyelven készült. Az IBM célja az üzleti, tudományos és rendszerprogramozási követelmények teljesítése volt. Vannak más nyelvek is, amelyeket figyelembe lehetett volna venni, de a PL / én a legteljesebb megoldást kínálta, annak ellenére, hogy még nem implementálták.A Multics projekt első néhány évében a nyelv egy részét lefordították assembly nyelvre az Early PL / I (EPL) fordítóval, Doug McIlroy és Bob Morris segítségével, a Bell Labs-tól.Az EPL addig támogatta a projektet, amíg a teljes PL / I számára nem sikerült elindítani egy boot-pántozó fordítót.
A Bell Labs 1969-ben kiszállt a Multics projektből: "Az idő múlásával a reményt frusztráció váltotta fel, mivel a csoport erőfeszítései kezdetben nem tudtak gazdaságilag hasznos rendszert előállítani."A további részvétel növelte volna a projekt támogatási költségeit. A kutatók tehát más fejlesztési lehetőségekhez fordultak.
A BCPL koncepciókon alapuló B rendszerprogramozási nyelvet Dennis Ritchie és Ken Thompson írta. Ritchie létrehozott egy rendszerindító-heveder-fordítót a B-hez, és megírta az Unics (Uniplexed Information and Computing Service) operációs rendszert a PDP-7-hez. Az Unics végül Unix-ként maradt fent.
A Bell Labs megkezdte a C egyik kiterjesztésének a fejlesztését és bővítését a B és a BCPL alapján. A BCPL-fordítót a Bell Labs szállította a Multics-ba, és a BCPL volt a preferált nyelv a Bell Labs-ben. Kezdetben a Bell Labs B fordítójának front end-programját használták, míg a C fordítót kifejlesztették.1971-ben egy új PDP-11 biztosította az erőforrást a B kiterjesztések meghatározásához és a fordító újraírásához.1973-ra a C nyelv tervezése alapvetően kész volt, és a PDP-11 Unix kernelét C-ben átírták. Steve Johnson elindította a Portable C Compiler (PCC) fejlesztését, hogy támogassa a C fordítókészülékek regenerálását az új gépekre.
Az objektumorientált programozás (OOP) érdekes lehetőségeket kínál az alkalmazás fejlesztéséhez és karbantartásához. Az OOP-koncepciók visszamenőleg visszatérnek, de a LISP és a szimuláció nyelvtudományának részét képezték. A Bell Labs-nél a C++ fejlesztők érdeklődését felkeltette az OOP. A C++ -ot először 1980-ban használták a rendszerek programozáshoz. Az eredeti kialakítás kihasználta a C nyelvi rendszerek programozási képességeit a Simula koncepciókkal. Az Objektumorientált lehetőségeket 1983-ban adtak hozzá. A Cfront program C++ kezelőfelületet valósított meg a C84 nyelvi fordítójára. A következő években több C++ fordítót fejlesztettek ki, ahogy a C++ népszerűsége növekedett.
Sok alkalmazási tartományban gyorsan felmerült egy magasabb szintű nyelv használatának gondolata. Az újabb programozási nyelvek által támogatott bővülő funkcionalitás és a számítógépes architektúrák növekvő bonyolultsága miatt a fordítók bonyolultabbá váltak.
A DARPA (Védelmi Fejlett Kutatási Projektek Ügynöksége) 1970-ben szponzorálta a Wulf CMU kutatócsoportjának fordítóprojektjét. A termelésminőség-fordító-fordító PQCC-tervezésével a forrásnyelv és a cél formális meghatározásaiból előállítanák a termelési minőség-fordítót (PQC). A PQCC megpróbálta kibővíteni a fordító-fordító kifejezést a hagyományos jelentéseken túl, mint értelmező generátor (például Yacc) nagy siker nélkül. A PQCC-t helyesebben fordítógenerátornak lehetne hivatkozni.
A PQCC kutatása a kódgenerációs folyamatban valóban automatikus fordító-író rendszer felépítését tűzte ki célul.Az erőfeszítés során felfedezték és megtervezték a PQC fázisszerkezetét. A BLISS-11 fordító biztosította a kezdeti struktúrát. A fázisok tartalmazták az elemzéseket (front end), a közbenső fordítást a virtuális gépre (middle end) és a célba történő fordítást (back end). A TCOL-t a PQCC kutatáshoz fejlesztették ki, hogy kezelje a nyelvspecifikus konstrukciókat a közbenső ábrázolásban. A TCOL változatai támogatnak különböző nyelveket.A PQCC projekt az automatizált fordítókészítés technikáit vizsgálta.A tervezési koncepciók hasznosnak bizonyultak az Ada objektumorientált programozási nyelvének és fordítóinak optimalizálásában.
Az Ada Stoneman dokumentum formalizálta a program-támogatási környezetet (APSE) a kerneltel (KAPSE) és a minimállal (MAPSE) együtt. Az Ada tolmács, a NYU / ED támogatta a fejlesztési és szabványosítási erőfeszítéseket az Amerikai Nemzeti Szabványügyi Intézettel (ANSI) és a Nemzetközi Szabványügyi Szervezettel (ISO). Az Ada katonai szolgálatának az USA katonai szolgálat általi kezdeti fejlesztése a Stoneman dokumentum mentén teljes integrált tervezési környezetbe foglalta a fordítókat. A hadsereg és a haditengerészet az Ada Language System (ALS) projekten dolgozott, amely a DEC / VAX architektúrára irányult, miközben a légierő az Ada Integrált Környezetben (AIE) indult az IBM 370 sorozat számára. Noha a projektek nem adták meg a kívánt eredményeket, hozzá járult az Ada fejlődésének általános hatásához.
Egyéb Ada-fordító kutatások kezdődtek Nagy-Britanniában a York-i Egyetemen és Németországban a Karlsruhe-i Egyetemen. Az Egyesült Államokban a Verdix (amelyet később a Rational vásárolt meg) szállította a Verdix Ada Fejlesztő Rendszert (VADS) a hadseregnek. A VADS egy sor fejlesztési eszközt biztosított, beleértve egy fordítót is.Az Unix / VADS különféle Unix platformon is elhelyezhető, mint például a DEC Ultrix vagy a Sun 3/60 Solaris, melyet a Motorola 68020-ra céloztak meg a hadsereg CECOM kiértékelése során. Hamarosan sok Ada-fordító állt rendelkezésre, amelyek teljesítették az Ada-érvényesítési teszteket. A Free Software Foundation GNU projekt kifejlesztette a GNU Compiler Collection (GCC) alkalmazást, amely alapvető képességet biztosít több nyelv és cél támogatására. Az Ada verziós GNAT az egyik legszélesebb körben használt Ada fordító. A GNAT ingyenes, de van kereskedelmi támogatás is, például az AdaCore-t 1994-ben alapították, hogy az Ada számára kereskedelmi szoftvermegoldásokat biztosítson. A GNAT Pro tartalmazza a GNU GCC alapú GNAT-ot egy eszközkészlettel, amely integrált fejlesztési környezetet biztosít.
A magas szintű nyelvek továbbra is elősegítették az összeállítók kutatását és fejlesztését. A fókuszterületek közé tartozik az optimalizálás és az automatikus kódgenerálás. A programozási nyelvek és a fejlesztési környezetek tendenciái befolyásolták a fordító technológiát.További fordítókat beillesztettek a nyelvi disztribúciókba (PERL, Java Development Kit) és az IDE alkotóelemeként (VADS, Eclipse, Ada Pro). Növekedett a technológiák kölcsönös kapcsolata és kölcsönös függősége. A webszolgáltatások megjelenése elősegítette a webnyelvek és a szkriptnyelvek növekedését. A parancsfájlok visszavezetik a parancssori felületek (CLI) kezdeti napjait, ahol a felhasználó megadhatott parancsokat, amelyeket a rendszer végrehajt. A felhasználói héj-koncepciók a nyelvekkel fejlesztettek ki shell programok létrehozására. A korai Windows tervek egyszerű batch programozási lehetőséget kínáltak. E nyelv hagyományos átalakítása értelmezőt használt. A Bash és a Batch fordítókat nem használták széles körben. Az utóbbi időben a kifinomult értelmezett nyelvek a fejlesztői eszközkészlet részévé váltak. A modern szkriptnyelvek közé tartozik a PHP, a Python, a Ruby és a Lua. (A Lua-t széles körben használják a játékfejlesztésben.) Mindegyik rendelkezik tolmács- és fordítói támogatással.
"Amikor az összeállítás területe az 50-es évek végén megkezdődött, a hangsúly a magas szintű nyelvi programok gépi kódra fordítására korlátozódott ...A fordító területe egyre inkább összefonódik más tudományágakkal, beleértve a számítógépes architektúrát, a programozási nyelveket, a formális módszereket, a szoftverfejlesztést és a számítógépes biztonságot. "A "Compiler Research: The Next 50 Year" cikk kiemelte az objektumorientált nyelvek és a Java fontosságát. A biztonságot és a párhuzamos számítástechnikát megemlítették a jövőbeli kutatási célok között.
Az 1990-es évek során nagy számban jelentek meg szabad fordítóprogramok a GNU projekt és a nyílt forráskód mozgalomban. Sok közülük nagyon jó minőségű.
Típusok
szerkesztésA fordítók egyik osztályozása az alapján történik, hogy a generált kódot melyik platformon szeretnénk végrehajtani. Ezt célplatformnak nevezik.
A natív vagy hosztolt fordító az amelynek kimenete közvetlenül ugyanazon a számítógépen és operációs rendszeren fut le, mint amin a fordító maga fut. A keresztirányú fordító kimenetét más platformon történő futtatásra tervezték. A keresztirányú fordítót gyakran olyan beágyazott rendszerekhez való szoftver fejlesztésekor használják, ahol ami nem támogatja magát a fejlesztési környezetet.
Azokat a fordítókat, amik egy virtuális gépnek (VM) állítanak elő futtatható kódot, nem szokták a natív vagy keresztirányú fordítók közé besorolni.
Habár az átlagos fordítók gépi kódra fordítják a forrás kódot, sok, ettől különböző fordító létezik:
- Forrásból-forrásba (source-to-source) fordítók olyan típusú fordítók, amik forrásnyelve és célnyelve egyaránt magas szintű programozási nyelv.
- A Bytecode fordítók egy elméleti gép assembly kódjára fordítják a forrásnyelvet, mint pl. néhány Prolog implementáció
- Ez a Prolog gép WAM-ként ismert
- A Java és a Python bytcode fordítói is ide tartoznak
- A futásidejű fordítás (Just-in-Time vagy JIT compiler) a bájtkódot a futási időben fordítja natív kódra. Sok különböző modern programozási nyelv is Ilyen fordítót használ pl. Java, Python, JavaScript, Microsoft .NET CLI. A JIT fordító egy interpreter belsejében fut. Amikor az interpreter érzékeli, hogy a kód útvonala "forró", azaz nemrég futtatott, a "felébreszti" a JIT fordítót ami aztán elvégzi a fordítást ezzel növelve a teljesítményt.
- Hardveres fordítók (hardware compiler, syntheses tools) kimenete utasítások sorozata helyett a hardver konfigurációja.
- Az assembler egy olyan program amely az ember által olvasható assembly nyelvet fordítja gépi kódra, amik a hardver által ténylegesen értelmezett utasítások.
- Az a program ami alacsony szintű nyelvről fordít magasabb szintű nyelvre decompilernek nevezik.
- A fordító ami magas szintű nyelvről fordít egy másik magas szintű nyelvre fordítónak (translator), source-to-source compilernek vagy nyelv újraírónak (rewriter) nevezik.
- Egy olyan programot, amely egy olyan objektumkód formátummá fordít, amelyet a fordítógép nem támogat, keresztirányú (cross-compiler) fordítónak nevezünk.
- Azt a programot, ami egy objektumkódot ugyanolyan objektumkóddá alakít optimalizációk és átalakítások közben, binary compilernek nevezzük.
Kapcsolódó szócikkek
szerkesztésForrások
szerkesztés- Interpreter and Compiler (angolul)
További információk
szerkesztés- A GNU fordítóprogram gyűjtemény
- Intel C fordítóprogramja (Windows / Linux alá)
- Csörnyei Zoltán: Fordítóprogramok. Typotex Kiadó, 2006. ISBN 963-9548-83-9