1 sohvi Sofistikoitunut hämäläinen variaabeleiden inspektori LKTT 2008 (per I-III) 25. ELOKUUTA 2008, VERSIO 10 Kielen määrittely annetaan laajennetulla BNF-notaatiolla, joka on seuraava. <nimi> ::= määrittely määrittelee välisymbolin nimi a1 a2 a1 jota välittömästi seuraa a2 a1 a2 a1 tai a2 [ a ] a tai ei mitään { a } nolla tai useampia kertoja a ( a1 a2 ) a3 kaarisulut määräävät vaikutusalueen (esimerkissä a1 tai a2 ja heti perään a3) Kun <nimi> esiintyy operaattorin ::= oikealla puolella, on sen merkitys täsmälleen sama kuin määrittely. 1. Perusrakenteita 1.1. Kommentti on merkkijono, joka a) alkaa ++ ja päättyy rivin loppuun, tai b) alkaa merkeillä (+ ja loppuu merkkeihin +) (voi siis olla useampirivinen). 1.2. Alkioiden (non-terminaalit) välissä saa olla tyhjiä merkkejä: välilyönti, rivinvaihto tai tabulaattori. 1.3. digit ::= 0 1... 9 1.4. integer ::= digit { digit } 1.5. scale_factor ::= ( E e ) [ + - ] integer 1.6. float ::= integer. integer [ scale_factor ] 1.7. number ::= integer float 1.8. letter ::= a... z A... Z ö Ö ä Ä 1.9. ident ::= letter { letter digit _ } 1.10. ident_list ::= ident {, ident } 1.11. full_ident ::= ident [ [ expression_list ] ] 1.12. qualident ::= { full_ident. } full_ident sohvi.tex 1 Rev: 10, August 25, 2008
2 1.13. designator ::= qualident 1.14. single_character ::= ascii merkki 32-255 1.15. character ::= single_character \ single_character 1.16. char_constant ::= character 1.17. string_constant ::= { character } 1.18. Kielen varatut sanat (tunnistetaan pienellä kirjoitettuna): addressof and apiece const div else end entry eval exit external fi finish function if import in internal is iterate launch map mod module monitor next not of or out perform pointer procedure protected repeat requires return returns stack struct type vector when while with Näiden lisäksi varattuja sanoja ovat myös kaikki kielen tietotyyppien nimet: bool, char, double, int, str, vector, map, stack, condition sekä sisäisten funktioiden ja proseduurien nimet: await, chr, convert, dispose, len, isempty, new, ord, pop, print, println, push, read, readln, signal, spawn, osoittimiin liittyvät nimet val, nil sekä vakiot true, false. 2. Kielen syntaksi 2.1. Käännösyksikkö 2.1.1. compilation ::= module { module } 2.1.2. module ::= module_type ident := [ import_part ] declaration_part procedure_part [ launch statement_sequence ] finish ident. 2.1.3. module_type ::= module monitor protected 2.2. Moduulin pääosat 2.2.1. import_part ::= import ident_list ; 2.2.2. declaration_part ::= { type_declaration ; variable_declaration ; } 2.2.3. procedure_part ::= { procedure_declaration ; function_declaration ; entry_declaration ; } sohvi.tex 2 Rev: 10, August 25, 2008
3 2.3. Peruslauseita 2.3.1. boolean_exp ::= expression 2.3.2. statement ::= assignment procedure_call if_statement loop_statement while_statement iterate_statement eval expression exit [ boolean_exp ] return [ expression ] 2.3.3. statement_sequence ::= [ with declaration_part perform ] statement ; { statement ; } 2.3.4. assignment ::= designator := expression 2.3.5. procedure_call ::= qualident [ actual_parameters ] 2.3.6. if_statement ::= if boolean_exp next statement_sequence { else if boolean_exp next statement_sequence } [ else statement_sequence ] fi 2.3.7. loop_statement ::= repeat statement_sequence finish 2.3.8. while_statement ::= while boolean_exp loop_statement 2.3.9. iterate_statement ::= iterate ident in range loop_statement apiece ident in expression loop_statement 2.3.10. range ::= expression.. expression 2.4. Funktiot ja proseduurit 2.4.1. fp_section ::= [ in ] [ out ] ident_list : type 2.4.2. formal_parameters ::= ( fp_section { ; fp_section } ) 2.4.3. procedure_heading ::= procedure ident [ formal_parameters ] 2.4.4. procedure_body ::= statement_sequence finish [ ident ] 2.4.5. procedure_declaration ::= procedure_heading := procedure_body 2.4.6. function_heading ::= function ident [ formal_parameters ] returns type 2.4.7. function_declaration ::= function_heading := procedure_body 2.4.8. entry_heading ::= entry ident [ formal_parameters ] when boolean_exp sohvi.tex 3 Rev: 10, August 25, 2008
4 2.4.9. entry_declaration ::= entry_heading := procedure_body 2.4.10. actual_parameters ::= ( [ expression_list ] ) 2.4.11. function_call ::= qualident actual_parameters 2.5. Tyypit ja muuttujat 2.5.1. type ::= qualident [ pointer ] 2.5.2. record_type ::= struct ident : type { ; ident : type }. 2.5.3. vector_type ::= vector [ range {, range } ] of type 2.5.4. map_type ::= map of type, type 2.5.5. stack_type ::= stack of type 2.5.6. type_declaration ::= type ident := ( type record_type vector_type map_type stack_type ) 2.5.7. map_val ::= factor : expression 2.5.8. map_init ::= { map_val {, map_val } } 2.5.9. vector_init ::= [ expression_list ] 2.5.10. initialization ::= expression vector_init map_init 2.5.11. variable_declaration ::= ident_list : type [ := initialization ] const ident := initialization 2.6. Lausekkeet 2.6.1. primary ::= number char_constant string_constant qualident function_call ( expression ) 2.6.2. prefix_op ::= + - not addressof 2.6.3. factor ::= [ prefix_op ] primary 2.6.4. mult_op ::= * / div mod 2.6.5. term ::= factor { mult_op factor } 2.6.6. add_op ::= + - & 2.6.7. simple_expression ::= term { add_op term } 2.6.8. relation_op ::= = # = = sohvi.tex 4 Rev: 10, August 25, 2008
5 2.6.9. relation ::= simple_expression [ relation_op simple_expression ] 2.6.10. expression ::= relation { and relation } relation { or relation } 2.6.11. expression_list ::= expression {, expression } 2.7. Import-moduulin rakenne 2.7.1. import_module ::= ident external [ requires_part ] import_declaration_part import_procedure_part. 2.7.2. requires_part ::= requires ident_list ; 2.7.3. import_type_declaration ::= type_declaration 2.7.4. import_variable_declaration ::= ident : [ const ] type internal string_constant 2.7.5. import_declaration_part ::= { import_variable_declaration ; import_type_declaration ; } 2.7.6. import_procedure_part ::= { procedure_heading internal string_constant ; entry_heading internal string_constant ; function_heading internal string_constant ; } sohvi.tex 5 Rev: 10, August 25, 2008
6 3. Tietotyypit 3.1. bool : totuusarvot true ja false. 3.2. char : ascii-merkki (8 bittinen). 3.3. int : etumerkillinen kokonaisluku, joka on yhteensopiva saman ympäristön C-kielisen int -tietotyypin kanssa (esim. 32 bittinen). 3.4. double : liukuluku, joka on yhteensopiva saman ympäristön C-kielisen double -tietotyypin kanssa (esim. 64 bittinen). 3.5. str : merkkijono (kuten C-kielessä eli ascii-merkit ja viimeisenä tavuna nolla). Merkkijonoa voi indeksoida, jolloin saatu yksittäinen merkki on tyyppiä char. 3.6. vector : Samaa tietotyyppiä sisältävä 1 N ulotteinen taulukko. 3.7. map : Assosiatiivinen taulukko. 3.8. stack : Pino, jota käsitellään aliohjelmilla push, pop ja isempty. 3.9. condition : monitorin ehtomuuttuja. 4. Semantiikkaa (tämä ei ole täydellinen luettelo, tarkista WWW-sivulta) 4.1. Leksikaalit 4.1.1. Merkkiliteraalien ja merkkijonojen yhteydessä voidaan käyttää merkintää \x, joka tarkoittaa merkkiä x itse tai erikoismerkintää jostain ohjauskoodista. Tällä tavoin saadaan kirjattua esim. merkkijonon sisään lainausmerkki. Ainakin seuraavien symbolien on toimittava: \n rivinvaihto (kuten C-kielessä) \t tabulaattori \0 nolla (merkkijonon lopetusmerkki) \ merkki itse (heittomerkki) \" merkki itse (lainausmerkki) \\ merkki itse (takakenoviiva) 4.1.2. Merkkijonon sisällä esiintyvät kommenttimerkit eivät aloita tai lopeta kommenttia. 4.1.3. Kielen varattu sana ei saa esiintyä muussa kuin syntaksin määräämässä merkityksessä. Varattu sana ei siis voi olla esim. moduulin, muuttujan tai tietotyypin nimenä. 4.1.4. qualident tarkoittaa pisteillä toisistaan eroteltuja nimiä (esim. moduuli.funktionimi ). sohvi.tex 6 Rev: 10, August 25, 2008
7 4.1.5. Nimien peittyminen on sallittua (eli jos esim. funktion parametrina on muuttuja i ja funktion rungossa silmukan silmukkamuuttuja on i, niin silmukan sisällä i-tarkoittaa silmukkamuuttujaa ja edellisen tason muuttujaan ei pystytä viittaamaan). 4.2. Moduulit 4.2.1. Määrittelyn lopussa oleva ident on sama kuin moduulin nimi. 4.2.2. Import-moduuli ei esiinny yksinään käännösyksikkönä, vaan se luetaan erillisestä tiedostosta import -lauseen seurauksena. 4.2.3. Import-moduulin requires -osassa luetellut moduulit otetaan automaattisesti mukaan käännökseen ( moduulinimi.o ) ja niiden alustuskoodi suoritetaan. 4.2.4. Ohjelmakoodi lähtee suoritukseen Main-nimisen moduulin alustuskoodista. Kaikki muut moduulit ovat käännösyksiköitä, joista tuotetaan esittelytiedosto ja objektitiedosto. 4.2.5. Esittelytiedosto tuotetaan nimelle moduulinimi.sohvidef 4.2.6. Kaikkien import-moduulina käyttöön otettujen moduulien alustuskoodit on suoritettava ennen Main:n käynnistymistä. 4.2.7. Jokaisen moduulin ohjelmakoodissa on globaali rutiini assemblernimellä moduulinimi$init, joka suorittaa moduulin alustuksen. 4.2.8. Import-moduulien internal -määreet (merkkijono) kertovat rakenteista käytettävän nimen assembler-tasolla. 4.3. Lauseet 4.3.1. for ja apiece -silmukan silmukkamuuttuja on näkyvissä ainoastaan silmukan sisällä. 4.3.2. Silmukkamuuttujaan ei saa sijoittaa. 4.3.3. Pinolle suoritettu apiece käy läpi pinon kaikki alkiot (suunnassa pinon päältä pohjalle ). 4.3.4. Map-taulukolle suoritettu apiece käy läpi taulukon kaikki avaimet type T = map of str, int; puhelinluettelo : T := { "jyke": 12345, "bitti": 45612 }; ++ tulosta kaikki numerot apiece nimi in puhelinluettelo repeat println( nimi, ":", puhelinluettelo[nimi] ); finish; sohvi.tex 7 Rev: 10, August 25, 2008
8 4.3.5. Taulukolle suoritettu apiece on määritelty vain yksiulotteisille taulukoille. 4.3.6. exit boolean_exp poistuu sisimmästä silmukasta jos ehtolauseen arvo on true. 4.3.7. exit -lause voi esiintyä ainoastaan silmukkarakenteen sisällä. 4.3.8. eval suorittaa lausekkeen ja hukkaa sen arvon (käytetään lähinnä silloin, jos halutaan kutsua funktiota ilman, että sen paluuarvolla on merkitystä). 4.3.9. with... perform luo uuden näkyvyysalueen, jossa määritellyt tyypit ja muuttujat ovat voimassa seuraavaan lohkon sulkevaan rakenteeseen. 4.4. Tietotyypit 4.4.1. Tietotyypeillä on rakenne-ekvivalenssi. 4.4.2. Automaattisia tyyppimuunnoksia tietotyyppien välillä ei ole olemassa. 4.4.3. Osoittimilla on erityinen tyhjä arvo nil, joka on tyyppiyhteensopiva kaikkien osoitintietotyyppien kanssa. 4.4.4. struct -tyyppi saa sisältää osoittimen samaa tietotyyppiä oleviin alkioihin. type IntList = struct x : int; next : IntList pointer end; 4.4.5. Jos osoitinta käytettäessä on yksikäsitteistä, että tarkoitetaan osoittimen päässä olevaa arvoa, toiminta tehdään automaattisesti. Jos käyttötilanne ei ole selkeä, kerrotaan varatulla sanalla val tilanteet joissa halutaan käyttää osoittimen päässä olevaa arvoa. nimi osoitin osoitin.val osoitin.nimi merkitys osoittimen arvo osoittimen osoittama arvo osoittimen päässä olevan struct:n kenttä (jolle tehdään tulkinta uudelleen) a, b : IntList; p, q : IntList pointer; p := nil; ++ sijoitetaan osoitinmuuttujaan tyhjä arvo sohvi.tex 8 Rev: 10, August 25, 2008
9 p := addressof a; q := addressof b; q.next := nil; q.x := 42; ++ tiedetään kohteen olevan muuttuja p.val := q.val; ++ q:n osoittama struct kopioidaan ++ p:n osoittamaan paikkaan p.next := q; p.next.x := 1; ++ muuttujan b kenttä x p.next.next := nil; p.next.next.val := b; ++ semanttisesti oikein, ++ viittaus nil:n läpi p := q; ++ osoitin q muuttujaan p 4.4.6. Eri tietotyyppien oletusalkuarvot ovat: false, a, 0, 0.0, "sohvi", nil ja condition -muuttujilla toteuksen mukainen alustus. 4.5. Lausekkeet 4.5.1. # on erisuuruusoperaattori. 4.5.2. boolean_exp on lauseke, jonka laskettu lopputulos on tietotyyppiä bool. 4.5.3. Peruslaskutoimitukset toimivat totutulla tavalla tietotyypeillä int ja double. 4.5.4. Perustietotyyppien välillä ei ole automaattisia tyyppimuunnoksia. (Erityisesti int ja double eivät ole yhteensopivia.) 4.5.5. mod ja div toimivat vain kokonaisluvuilla int ja toteuttavat ehdot x = (x div y) y + (x mod y) 0 (x mod y) < y tai y < (x mod y) 0 4.5.6. Merkkijonoilla str katenointi ( & ) tuottaa uuden merkkijonon, joka on yhdistelmä laskun termeistä. 4.5.7. Operaattori addressof antaa muuttujaan viittaavan osoittimen. 4.5.8. Osoittimien arvoilla toimivat yhtä- ja erisuuruusvertailut. 4.5.9. and ja or noudattavat oikosulkuevaluointia (ketjutetun lausekkeen laskeminen lopetetaan heti kun sen lopputulos on tiedossa). 4.6. Muuttujat 4.6.1. const -muuttujien tietotyyppi määräytyy määrittelyn alustuslausekkeen tietotyypin mukaan. sohvi.tex 9 Rev: 10, August 25, 2008
10 4.7. Funktiot ja proseduurit 4.7.1. Aliohjelmaa (procedure) saa kutsua vain lauseessa. 4.7.2. Funktiota saa kutsua vain lausekkeessa (erillisenä lauseena kutsu tehdään eval -lauseen avulla). 4.7.3. Funktiot ja proseduurit ovat ylimääriteltyjä siten, että nimen lisäksi tarvitaan parametrien lukumäärä ja tietotyypit tunnistamaan aliohjelma. Sisäisiä funktioita ei saa ylimääritellä. 4.7.4. Funktion ja proseduurin määrittelyn lopussa oleva ident on oltava sama kuin ko. aliohjelman nimi (koodin selkeyteen tähtäävä syntaksi). 4.7.5. Parametrimääreiden toiminta: Määre <tyhjä> in out in out Käyttö sijoituksessa Luku ja kirjoitus. Kuten paikallinen muuttuja (arvoparametri). Vain luku. Vakioparametrimuuttuja. Vain kirjoitus. Viitepaluuarvo. Luku ja kirjoitus. Kuten viiteparametri. 4.7.6. Arvon palauttaminen return -lauseella proseduurista on virhe. 4.7.7. Tyhjä return -lause funktiossa on virhe. sohvi.tex 10 Rev: 10, August 25, 2008
11 4.7.8. Kielen sisäiset funktiot Nimi len(x) Argumentin tyyppi str, vector, stack Tulostyyppi int Toiminta x:n pituus (alkioiden lukumäärä, jossa merkkijonoilla ei ole mukana loppunollaa) ord(x) char int x:n järjestysnumero chr(x) 0 int char x:s ascii-merkki 255 pop(p) pino arvo Palauttaa pinon päällimmäisen alkion ja samalla poistaa ko. alkion pinosta. Jos pino on tyhjä, niin toiminta on määrittelemätön isempty(p) pino bool Palauttaa true jos pino on tyhjä, muutoin false convert(x,t) X T Palauttaa arvon joka on tietotyyppiä T ja jonka arvo on x 4.7.9. convert -funktion tulee ymmärtää vähintään muunnokset Muunnos convert(d, int) convert(i, double) Toiminta Palauttaa suurimman kokonaisluvun joka on d Palauttaa liukuluvun, jonka arvo on i sohvi.tex 11 Rev: 10, August 25, 2008
12 4.7.10. Kielen sisäiset proseduurit read(m,s) readln(m,s) muuttuja ja boolean status muuttuja ja boolean status Nimi Argumentin Toiminta tyyppi spawn(x) katso 5.1.1 käynnistää uuden suoritussäikeen await(x) condition jää odottamaan ehdon toteutumista signal(x) condition signaloi ehdon toteutuneen new(p) osoitinmuuttuja dynaaminen muistinvaraus, johon mahtuu osoittimen tietotyyppiä oleva alkio, osoitinmuuttuja osoittaa varattuun lohkoon dispose(p) osoitinmuuttuja poistaa osoittimen päässä olevan alkion käytöstä ja asettaa parametrina olevan osoittimen arvoksi nil. print(a,b,...) luettelo dataa tulostaa parametrit println(a,b,...) luettelo dataa toimii kuten print, mutta tulostaa viimeisenä rivinvaihdon lukee käyttäjältä merkkejä, jotka muunnetaan parametrin m arvoksi. s on true on muunnos onnistui. (Toteutusvinkki: scanf()) lukee käyttäjältä rivin merkkejä, jotka muunnetaan parametrin m arvoksi. s on true on muunnos onnistui. Myös rivinvaihtomerkki luetaan pois syötteestä. push(p,x) pino ja arvo laittaa pinon p päällimmäiseksi uuden arvon x (joka on pinon tyyppiä). 4.7.11. int, double ja str tietotyyppien parametrinvälityksen on oltava yhteensopiva C-kielestä tuotetun koodin kanssa (C:n vastaavat tietotyypit int, double ja char*). Tämä takaa sen, että sohvi-ohjelmat voivat käyttää C-kielellä tehtyjä kirjastoja. sohvi.tex 12 Rev: 10, August 25, 2008
13 4.7.12. await ja signal proseduureja voi käyttää ainoastaan monitorrakenteen sisällä. 4.7.13. Osoitintyypeille määritellyt new ja dispose varaavat ja vapauttavat dynaamista muistia. Molemmat ottavat yhden osoitintyyppisen argumentin. Lause new(p); varaa p:n osoittaman tyypin tarvitseman määrän dynaamista muistia, ja lause dispose(p); vapauttaa p:n osoittaman muistin. Lauseen new(p) suorittamisen jälkeen p sisältää varatun muistilohkon osoitteen (tai nil jos muistinvaraus epäonnistui). 5. Rinnakkaisuusominaisuudet 5.1. Suoritussäikeet 5.1.1. Kutsu spawn(p, i) käynnistää uuden suoritussäikeen, joka ryhtyy suorittamaan proseduuria p. Proseduurin esittelyn eli signatuurin tulee olla muotoa: procedure p( i : integer ); Uuden säikeen käynnistyessä aliohjelma p saa parametrinaan spawnkutsun toisen parametrin (kokonaisluku). 5.1.2. Säikeen suoritus päättyy kun se palaa aliohjelmasta. Vastaavasti Main-säie lopettaa kun se suorittanut Main-moduulin alustuksen viimeisen lauseen. 5.1.3. Koko ohjelman suoritus päättyy kun kaikki sen käynnistämät spawnsäikeet ja Main-säie ovat lopettaneet suorituksensa. 5.2. Monitor 5.2.1. Monitor-moduulin kaikki aliohjelmat suorittavat keskinäisen poissulkemisen siten, että vain yksi suoritussäie kerrallaan voi olla suorittamassa moduulin määrittelemää koodia kerrallaan. 5.2.2. Monitorin esittelemät muuttujat eivät ole käytettävissä moduulin ulkopuolelta (ne eivät ole näkyvissä import-lauseen avulla). 5.2.3. Tietotyyppi condition sekä proseduurit await() ja signal() ovat käytettävissä ainoastaan Monitor-moduulin sisällä. 5.2.4. signal(x) siirtää välittömästi monitorin suoritusvuoron yhdelle ehtomuuttujassa x odottavalle säikeelle. Jos yhtään odottajaa ei ole olemassa, niin proseduuri ei tee mitään. 5.3. Protected 5.3.1. Poissulkemisen ja näkyvyyksien kannalta Protected-moduuli käyttäytyy kuten Monitor-moduuli. sohvi.tex 13 Rev: 10, August 25, 2008
14 5.3.2. Entry-aliohjelmat ovat käytettävissä ainoastaan Protected-moduulin sisällä. 5.3.3. Entry-aliohjelmaa kutsuttaessa se suoritetaan ainoastaan, jos aliohjelman when -ehtolause evaluoituu arvoon true. Jos ehto ei toteudu niin kutsun tehnyt säie jää odottamaan kyseisen entryaliohjelman jonoon. 5.3.4. Jokaisen protected-moduulin aliohjelman suorituksen jälkeen (ennen moduulin poissulkemisen lukituksen vapauttamista) tarkastetaan odottavien entry-aliohjelmien ehdot ja jos toteutunut ehto löydetään, niin suoritusvuoro annetaan tälle suoritussäikeelle (entry-jonot siis ohittavat mahdollisesti ulkupuolelta moduuliin samanaikaisesti tulevat kutsuyritykset). Vaikka toteutuneita ehtoja olisi useampia vain yksi odottava säie herätetään suoritukseen. sohvi.tex 14 Rev: 10, August 25, 2008
15 6. Käyttöliittymä 6.1. Kääntäjää ajetaan komennolla sohvic 6.2. Kääntäjän on ymmärrettävä seuraavat komentoriviparametrit -h tulostaa käyttöohjeen. tiedosto(t) luettelo lähdekooditiedostoja. -o btiedosto valmis binääri tulee nimelle btiedosto (oletuksena sohvi.out). -S käännös tuottaa tiedostoon moduulinimi.s käännöksen LLVMassembler muodossa. -llib linkittää mukaan kirjaston lib, joka on yhteensopiva C-kirjaston kanssa (esim. libcurses). -Lpath hakemisto, josta kirjastoja, moduuleja ja import-esittelyitä etsitään (jos tarvitaan useampia hakemistoja, niin valitsin annetaan useamman kerran). Työskentelyhakemisto on aina mukana etsinnässä. -Xstring asettaa päälle toteuttajien oman laajennuksen kääntäjässä. Esimerkkinä vaikkapa -Xgs ottaa käyttöön roskienkeruun tuotetussa binäärissä tai -Xjava tuottaa suoritettavan koodin javan tavukoodina. 6.3. Kääntäjä osaa ottaa itse automaattisesti mukaan kaikki tarvitsemansa apukirjastot ilman että käyttäjän tarvitsee niitä luetella -l ja -L vipusilla. Omat apukirjastot tulee sijoittaa hakemistoon, joka on kerrottu kääntäjän käännösvaiheessa Makefilen PREFIX-muuttujalla (katso tarkemmin työn palautusohjeista WWW-sivuilla). 6.4. Vinkki: tätä kaikkea ei ole tarvis nysvätä itse, vaan osan ominaisuuksista voi toteuttaa käyttämällä hyväksi valmiita työkaluja (llvm-gcc ja llvm-sovelluskehyksen työkalut). Sopivilla parametreilla ja vipusilla kirjastojen linkitys mukaan yms. saa toteutettua helposti. sohvi.tex 15 Rev: 10, August 25, 2008