Ajattelin esitellä tällä foorumilla Pythonilla tekemääni kääntäjää yksikertaiselle korkean tason ohjelmointikielelle. Kääntäjä kääntää kielen AT&T-syntaksia käyttäväksi AMD64-assmemblyksi. Tästä assmeblysta tuotetaan sitten suoritettava elf-tiedosto käyttöjärjestelmän assemblerilla. Kääntäjässä on noudatettu pitkälti samoja käytänteitä, joita esitellään Helsingin yliopiston kääntäjä -kurssin web-sivuilla. Joitain erovaisuuksia siis on web-sivulla esiteltäviin kääntäjätekniikan menetelmiin, kuten esimerkiksi sokerinpilkkojien käyttö ennen jäsentämistä, string pool -tekniikan käyttö merkkijonojen toteutuksessa ja myös itse kielen ominaisuuksista löytyy eroja. Sivustolla esiteltävä esimerkkikieli on hyvin pitkälti sama kuin oman kääntäjäni tukema kieli, mutta silti pieniä eroja löytyy.
Koodi itsessään on paikoin hyvinkin sitä kuuluisaa spagettia. Tosin en ole mitenkään päämäärätietoisesti tai systemaattisesti tehnytkään tätä projektia, ja se tietysti näkyykin koodin laadussa. Lähinnä olen uteliaisuuden ja kokeilemisen halun kautta tätä projektia työstänyt kuin tavoitteellisesti laadukkaan kääntäjän kehittämiseksi (enkä edes osaisi sellaista tehdäkään :D). Seuraavaksi voisin tietysti refaktoroida koodia järkevämmäksi, jotta sieltä karsiutuisi pois ainakin räikeimmät hajamieliset ratkaisut ;)
Kieli on siis C-kielen syntaksia muistuttava, rekursiivinen korkean tason ohjelmointikieli. Alla tiivistetty listaus kielen ominaisuuksista
Funktiot ovat aliohjelmia, jotka ovat aina ns. puhtaita. Ne eivät siis voi käsitellä muuttujia tai mitään muutakaan, joka on määritelty funktioiden ulkopuolella. Funktioille voi antaa ja määritellä enintään 6 parametria, sillä kieli (ja kääntäjä) ei käytä System V 64bit Calling Convention mukaista määräystä pinon käytöstä lisäparametrien välityksessä.
Tyypitys kielessä on alkeellinen. Muuttujille ja funktioille ei ole pakollista määritellä tietotyyppiä. Kääntäjässä on pieni tyyppitarkastaja, joka tarkistaa binäärioperaatioiden validiteetin ja muuttujien alustuksen. Tyyppitarkastus on buginen ja voi johtaa välillä erikoisiin virheilmoituksiin ja -tilanteisiin, kun syötetään epäkelvollisia binäärioperaatioita. Tyyppitarkastusta täytyy todellakin hioa jatkossa paremmaksi, jos jaksan vielä tätä projektia edistää.
Taulukoiden tarvitsema tila varataan jo käännöksen aikana bss-muistialueelle. Taulukoiden koko täytyy antaa koko siis vakiona. Taulukoiden arvot ovat muistiosoitteita. Muistiosoitteista löytyy sitten todelliset taulukon alkioiden arvot. Ne voivat sitten olla merkkijonojen alkuja, kokonaislukuja jossain pinossa tai toisia taulukoita.
Merkkijonot luodaan käännöksen aikana data-alueelle (oikeastaan erityiseen taulukkoon, joka on mukana kielen standardikirjastossa) ja muuttujat ovat viitteitä merkkijonojen alkuun tähän taulukkoon. Merkkijonoja käsitellään siis kielen oman std-kirjaston kautta.
Taulukoiden ja merkkijonojen toteutuksesta tulee varmasti mieleen monia näkökulmia, koska tämä nykyinen tekninen toteutustapa on kieltämättä vähän epäoptimaalinen. Esimerkiksi taulukot eivät voi olla tehokkaita jo pelkästään siksi, kun jokaisen arvon ollessa muistiosoite, ei suorittimen välimuisti voi toimia tehokkaalla tavalla. Toisaalta tällainen "array of references"-ratkaisu voi ohjelmoijan näkökulmasta selkeä. Sehän muistuttaa tällöin pitkälti tulkattavien kielien taulukoita (vrt. esim. Python).
Kääntäjän välikieli (intermediate representation) on lähestulkoon juuri sellainen mikä HY:n kääntäjä -kurssin www-sivuille esitellään.
Jos kääntäjällä tuotetaan suoritettavia elf-tiedostoja, binääriin liitetään kielen standardikirjasto, jossa on mm. funktiot ja globaalit muuttujat taulukoiden käsittelyä ja merkkijonoja varten. Ja vielä kerrataan, että elf-tiedosto muodostetaan käyttöjärjestelmän työkaluilla. Tämä ohjelma ei rakenna teksti-assemblystä elf-tiedostoa!
Toivottavasti tämä ei ollut ainakaan kovin sekava esittelypostaus tälle projektilleni. En rupea nyt enempää selostamaan teknisiä toteutuksia ym., mutta jos kysytte jotain, pyrin vastailemaan kysymyksiin tällä foorumilla. Jotain tarkempaa dokumentointia löytyy projektin repositoriosta. Tosin projektin dokumentaatio on vielä pahasti keskeneräinen.
Tulevaisuudessa lisättäviä ominaisuuksia voisivat olla esimerkiksi
Toki mielestäni tärkeämpiä seuraavia steppejä olisi kyllä tyyppitarkastuksen hiominen ja yleinen koodin siistiminen. Myös merkittävät rajoitteet, eli merkkijonoa ei voi palauttaa tyyliin
return "hello world";
ja tokenizerin puute koskien negatiivisia kokonaislukuja, täytyy paikata!