Seppo Mustonen: Sukrojen ohjelmointi Survossa

4. Sukromuisti

Sukrot tukeutuvat Survon tiedonhallintaan ja ne voivat tallettaa ja poimia tietoja kaikilla Survon tuntemilla keinoilla. Näin esim. toimituskentät ja havainto- ym. Survon tiedostot toimivat tarvittaessa sukrojen muisteina. Tietojen välittömään hallintaan esim. ehdollisissa toiminnoissa sukroilla on lisäksi käytössä oma keskusmuistissa oleva tila, jota sanomme sukromuistiksi. Tästä käytettiin aikaisemmin nimeä sukropino (tutstack), koska tietoa saatettiin pinota vain aikaisemman tiedon jatkeeksi. Nyt tästä rajoituksesta on vapauduttu niin, että mikä tahansa talletettava tieto on sijoitettavissa myös aikaisempien väliin.
     Sukromuistin rakennetta ei kuitenkaan ole muutettu. Se on yksinkertaisesti merkkijono, joka koostuu merkkeihin @ päättyvistä sanoista. Sukromuistissa olevat sanat voivat olla sekä lukuja että ei-numeerisia, tekstityyppisiä tietoja. Niitä vastaaviin muistipaikkoihin viitataan sukrokielessä merkinnöin W1,W2,..., jotka on mahdollista muuttaa kussakin sukrossa myös selväkielisiksi W-alkuisiksi nimiksi.
     Sukrot kokoavat tietoa sukromuistiin mm. toimituskentästä ja kysymyksistä, joita sukro esittää käyttäjälle. Muistiin poimittuja sanoja voidaan sitten kirjoittaa toimituskenttään ja käyttää ehdollisten, sukron jatkotoimintaa koskevien päätelmien pohjana. Sukromuistin sisällä tietoja voi kopioida paikasta toiseen ja muistiin talletetuilla luvuilla voi rajoitetusti myös laskea.

Sukromuistin alustus sukron parametreilla

Kun sukro käynnistetään toimituskentästä komennolla, jossa on komentosanana sukron nimi (edessä /) ja perässä joukko pilkuin tai välilyönnein erotettuja parametreja (esim. /PIEN 19.1,12), parametrit sijoittuvat tässä järjestyksessä muistipaikkoihin W1,W2,... (eli W1=19.1 ja W2=12).
     Ajatelkaamme, että sukron PIEN tarkoituksena on ilmoittaa, kumpi parametreina annetusta luvusta on pienempi. Siis yo. tapauksessa sen tulisi kirjoittaa seuraavalle toimituskentän riville lause "Luvuista 19.1 ja 12 pienempi on 12.").
     Sukron PIEN ohjelmakoodi ja toiminta ilmenee seuraavasta:
   9  1 SURVO 84C EDITOR Sat Apr 27 13:41:05 1991         C:\SUOPAS\ 120  80 0
  15 *
  16 *TUTSAVE PIEN
  17 *{R}{erase}{erase}
  18 - if W1 < W2 then goto A1
  19 - if W2 < W1 then goto A2
  20 *Luvut {print W1} ja {print W2} ovat yhtäsuuret.{goto L}
  21 + A1: {W3=W1}{goto B}
  22 + A2: {W3=W2}
  23 + B: Luvuista {print W1} ja {print W2} pienempi on {print W3}.
  24 + L: {end}
  25 *
  26 */PIEN 19.1,12
  27 *Luvuista 19.1 ja 12 pienempi on 12.
  28 *
  29 *TUTSTACK_
  30 *19.1@12@12@
  31 *

Riveillä 17-24 oleva ohjelma on talletettu TUTSAVE-komennolla sukroksi PIEN. Ohjelmaa testataan rivillä 26, jolloin sen antama tulos syntyy riville 27. Ohjelmassa riveillä 18 ja 19 olevat vertailut johtavat siihen, että pienempi luvuista W1 ja W2 kopioidaan sijoituslauseella {W3=W1} tai {W3=W2} muistipaikkaan W3, jolloin rivillä 23 oleva koodi kirjoittaa vaaditun lauseen. Tässä lauseessa käytetään tulostuskäskyjä {print W1} jne. sukromuistin sisältämien tietojen kirjoittamiseen. Huomaa myös, että tasatilanteessa joudutaan riville 20, joka kirjoittaa vastaavan tuloksen.
     Sukromuistin sisältö voidaan listata toimituskenttään TUTSTACK-komennolla, kuten on tehty rivillä 29. Muistin sisältö merkkijonona ilmestyy seuraavalle riville (30).

Jos sukro käynnistetään ilman parametreja (esim. /KOE), sukromuisti alustetaan yhdellä sanalla W1=(empty). Tämän tiedon avulla sukro voi esim. tutkia odottamiensa parametrien puuttumista. Esim. äskeisen PIEN-sukron alussa voisi olla testi

    - if W1 '<>' (empty) then goto Jatko
    *Vertailtavat luvut puuttuvat!{goto L}
    + Jatko: ...
Tässä relaatio '<>' tarkoittaa merkkijonojen erilaisuutta; siis jos ensimmäinen parametri ei ole (empty), hypätään eteenpäin kohtaan Jatko, muuten kirjoitetaan lukujen puuttumista koskeva ilmoitus ja lopetetaan.
     Jos Survo otetaan käyttöön sukron avulla (kts. kohtaa Survon käynnistys sukrolla luvussa 11), tulee muistipaikan W1 sisällöksi poikkeuksellisesti W1=(start) . Näin sukro kykenee tunnistamaan, milloin sitä käytetään aloitussukrona.

Sukromuistin tyhjennys ja talletus

Sukromuisti tyhjennetään kokonaan koodilla {del stack} ja esim. muistipaikasta W3 eteenpäin koodilla {del stack W3}. Muistiin sijoitettavien sanojen lukumäärää eikä pituutta ei ole periaatteessa rajoitettu, mutta sukromuistin enimmäispituus on nykyisellään 255 merkkiä. (SURVO 98:ssa 1000 merkkiä.) Tilan ylityksestä tulee virheilmoitus ja sukron toiminta keskeytyy. Koska sukromuistia käytetään vain väliaikaisiin talletuksiin, em. rajoitus ei ole käytännössä vakava.
     Joskus on tarpeen tehdä sukromuistin sisällöstä "varakopio". Se tapahtuu käskyllä {save stack}. Näin talletettu muistin sisältö saadaan takaisin nykyisen sisällön jatkeeksi käskyllä {load stack}.

Seuraava esimerkki havainnollistaa tämänkaltaista sukromuistin hallintaa:
  16  1 SURVO 84C EDITOR Sun Apr 28 07:52:00 1991         C:\SUOPAS\ 120  80 0
  33 *
  34 *TUTSAVE MUISTI1_
  35 *{del stack}
  36 / Muisti tyhjennetty.
  37 /
  38 *{W1=7}{W2=25}{save stack}
  39 / Sisältö 7@25@ talletettu.
  40 /
  41 *{W1=W1+W2}
  42 / Laskettu W1=7+25=32, jolloin muistissa 32@25@
  43 /
  44 *{del stack W2}
  45 / Muisti tyhjennetty sanasta W2 eteenpäin. Muistissa 32@
  46 /
  47 *{load stack}
  48 / Talletettu sisältö otettu nykyisen jatkeeksi. Muistissa 32@7@25@
  49 /
  50 *{end}
  51 *

Sukromuistin koko sisältö on mahdollista tallettaa tiedostoon käskyllä {save stack ABC}, missä ABC tarkoittaa tiedoston nimeä. Tiedoston oletuspolku on Survon väliaikaisten tiedostojen hakemisto, joka on määritelty rivillä tempdisk systeemitiedostossa SURVO.APU . Jos ko. hakemistoa ei ole annettu, käytetään Survon päähakemiston alla olevaa TMP-hakemistoa. Tiedostoon ABC talletettu sukromuisti poimitaan takaisin käskyllä {load stack ABC}, jolloin muistin aiempi sisältö tuhoutuu. (Huomaa ero käskyyn {load stack}.)
     Tiedoston nimen saa antaa myös itse sukromuistin välityksellä eli esim. {save stack W3} .

Laskutoimituksista

Editoriaalista ja kosketuslaskentaa on luonnollista käyttää sukrojen tukena. Kuten jo edellisestä esimerkistä ilmeni, sukromuistissa on mahdollista tehdä myös suoraan yksinkertaisia aritmeettisia laskutoimituksia. Tähän aiheeseen palataan tarkemmin vasta myöhemmin.
     Mainittakoon kuitenkin jo nyt, että käytettävissä on mm. neljä peruslaskutapaa:

    {Wi=Wj+Wk} {Wi=Wj-Wk} {Wi=Wj*Wk} {Wi=Wj/Wk}
Muistipaikkojen asemasta operandeina saattaa esiintyä myös vakioita. Esim. {W5=W5+1} tarkoittaa, että muistipaikan W5 nykyistä arvoa kasvatetaan yhdellä.

Tietoja (sekä lukuja että merkkijonoja) siirretään paikasta toiseen kopiointikäskyillä {Wi=Wj}. Niitä voi myös kytkeä peräkkäin käskyllä {Wi=Wj&Wk}. Esim. käskyt

    {W1=SURVO}{W1=W1& 84C}
saavat aikaan, että paikan W1 sisällöksi tulee "SURVO 84C".

Muistipaikkojen nimeäminen

Sukromuistin muistipaikoille W1,W2,... annetaan tarvittaessa W-alkuiset selväkieliset nimet selitysriveillä, jotka ovat muotoa

    / def Wnimi1=W1 Wnimi2=W2 Wnimi3=W3
    / def Wnimi4=W4 Wnimi5=W5
Nimien käyttö parantaa ohjelman luettavuutta. Usein ohjelmaa kehiteltäessä joutuu myös muuttamaan asioiden paikkoja sukromuistissa; tarvitaan esim. uusia parametreja. Tällaisista muutoksista selvitään korjaamalla vain def-selitysrivit eikä ole aihetta kajota itse ohjelmakoodissa muistipaikkojen indekseihin.
     Saman muistipaikan saa jopa nimetä ohjelmassa useaan kertaan eri tunnuksilla.

Seuraava sukro muodostaa editoriaalisella laskennalla kahden annetun luvun pienimmän yhteisen jaettavan ja kirjoittaa tuloksen lauseena tyyliin: "Lukujen 144 ja 54 pienin yhteinen jaettava on 432."

  12  1 SURVO 84C EDITOR Sun Apr 28 08:51:44 1991         C:\SUOPAS\ 120  80 0
   1 *
   2 *TUTSAVE PYJ_
   3 /  /PYJ M,N laskee positiivisten kokonaislukujen pienimmän yhteisen
   4 /           jaettavan lausekkeena M*N/gcd(M,N), missä gcd(M,N) on
   5 /           lukujen suurin yhteinen tekijä (Survon kirjastofunktio).
   6 /
   7 / Siirrytään suurempaan nopeuteen ja alustetaan kenttä:
   8 *{tempo -1}{init}
   9 /
  10 / Lisätään tyhjä rivi vastausta varten ja siirrytään sen alkuun:
  11 *{ins line}{line start}
  12 /
  13 / def WM=W1 WN=W2 Wpyj=W3  (nimetään muistipaikat)
  14 /
  15 / Lasketaan M*N/gcd(M,N):
  16 *{print WM}*{print WN}/gcd({print WM},{print WN})={act}
  17 /
  18 / Rivin alussa näkyy esim. 144*54/gcd(144,54)=432
  19 / Siirrytään pykälä vasemmalle ja kirjoitetaan välilyönti,
  20 / jolloin = häviää:  (tyhjä koodi {} osoittaa, että väli kuuluu riville)
  21 *{l} {}
  22 /
  23 / Rivillä näkyy nyt esim.  144*54/gcd(144,54) 432
  24 / Talletetaan kohdistimen osoittama luku (432) muistipaikkaan Wpyj:
  25 *{save word Wpyj}
  26 /
  27 / Siirrytään rivin alkuun, tyhjennetään ja kirjoitetaan vastaus:
  28 *{line start}{erase}Lukujen {print WM} ja {print WN} pienin yhteinen j
  29 *aettava on {print Wpyj}.
  30 /
  31 / Palautetaan alkuperäinen nopeus ja lopetetaan:
  32 *{tempo +1}{end}
  33 *

Huomaa, miten sukro synnyttää lausekkeen arvon editoriaalisella laskennalla, eristää tuloksen lausekkeesta (korvaamalla merkin = välilyönnillä) ja poimii sen sukromuistiin käskyllä {save word Wpyj}.
     Ohjelmalistaus on hiukan ylikommentoitu. Näytteenä normaalimmasta kirjoitustavasta otamme edellisen yleistyksenä sukron SYTPYJ, joka ilmoittaa kaksirivisenä lauseena sekä suurimman yhteisen tekijän että pienimmän yhteisen jaettavan:

  33  1 SURVO 84C EDITOR Sun Apr 28 09:21:12 1991         C:\SUOPAS\ 120  80 0
  38 *
  39 *TUTLOAD SYTPYJ
  40 / /SYTPYJ M,N laskee positiivisten kokonaislukujen suurimman yhteisen
  41 /             tekijän ja pienimmän yhteisen jaettavan.
  42 / def WM=W1 WN=W2 Wsyt=W3 Wpyj=W4
  43 /
  44 *{tempo -1}{init}{ins line}
  45 /
  46 / Lasketaan SYT:
  47 *{line start}gcd({print WM},{print WN})={act}{l} {save word Wsyt}
  48 /
  49 / Lasketaan PYJ:
  50 *{line start}{erase}{print WM}*{print WN}/{print Wsyt}={act}{l} {}
  51 *{save word Wpyj}
  52 /
  53 / Kirjoitetaan tulos kahdelle riville. Rivi 1:
  54 *{line start}{erase}Lukujen {print WM} ja {print WN} suurin yhteinen
  55 * tekijä on {print Wsyt}
  56 /
  57 / Rivi 2:
  58 *{ins line}{line start}ja pienin yhteinen jaettava {print Wpyj}.
  59 *{tempo +1}{end}
  60 *
  61 *
  62 */SYTPYJ 144,54
  63 *Lukujen 144 ja 54 suurin yhteinen tekijä on 18
  64 *ja pienin yhteinen jaettava 432._
  65 *

Mallisovellus näkyy riveillä 62-64.

Sukrojen ohjelmointi Survossa - Seppo Mustonen 1991
  1. Johdanto
  2. Esimerkki
  3. Sukrokielen koodisanoja
  4. Sukromuisti
  5. Hapuilukoodit, tulostus ja kohdistimen liikuttelu
  6. Sukrojen aloittaminen ja kytkeminen toisiinsa
  7. Ehdolliset toiminnat
  8. Käyttäjän vuorovaikutus
  9. Aritmetiikka ja muistin välitön hallinta
  10. Sukrotiedostot
  11. Sukrojen lajit
  12. Sukrojen laatiminen käytännössä
  13. Virhetilanteet
  14. Näytesovelluksia
Liite: Sukrokielen koodisanat