Seppo Mustonen: Sukrojen ohjelmointi Survossa

2. Esimerkki

Johdattelevana esimerkkinä käsittelemme pienen sukron laatimista. Vastaavan englanninkielisen sukron teko esitellään Survon opetussukrojen joukossa otsikolla "How to make sucros".
     Oletamme, että Survo on käytössämme ja haluamme määritellä sukron, joka kirjoittaa kellonajan toimituskenttään seuraavan rivin alkuun. Sukro voitaisiin kirjoittaa suoraan sukrokielellä, mutta teemme sen aluksi opetustilassa antamalla Survon tallettaa kaikki työvaiheet.
     Sukron määrittely alkaa painamalla näppäimiä PREFIX ja T. Tällöin näytön alimmalle riville, Survon ikkunan alapuolelle, ilmestyy kysymys:

   Sucro functions: S=Start definition, R=Run ? _
Kun painetaan nappia S, kysymys korvautuu toisella:
   Define a sucro: Name of file ? _
Kirjoitamme valitsemamme nimen AIKA ja painamme nappia ENTER. Tällöin Survo sen kummemmitta ilmoituksitta perustaa sukrotiedoston AIKA.TUT tämänhetkiseen Survon datahakemistoon. Kysymysrivi katoaa ja toimituskenttä näkyy normaaliin tapaan. Kuitenkin tästä lähin kaikki toimenpiteemme (näppäimien painallukset) tulevat tallentumaan tiedostoon AIKA.TUT.
     Näkyvänä osoituksena siitä, että sukron teko (tai sen toiminta yleensäkin) on käynnissä, toimituskentän otsikkorivin eteen ilmaantuu numero 1, joka kuvaa, millä sukrojen tasolla tällä hetkellä toimitaan. Silloin kun sukrot kutsuvat toisiaan aliohjelmina, ko. tasonumero kasvaa yhdellä aina uuden aliohjelman aloittaessa ja vähenee vastaavasti sukron lopettaessa. Se, että tasonumeroa ei näy (eli se on 0), on merkki siitä, ettei mikään sukro ole toiminnassa eikä määrittelyn alaisena.

Olettakaamme, että kohdistin on (ei välttämättä tyhjässä kentässä) rivillä 3 ja painamme nappia ENTER, jolloin kohdistin siirtyy seuraavan rivin (4) alkuun. Kirjoitamme sitten Survon tunteman komentosanan TIME ja painamme vielä välilyöntinäppäintä. Toimituskentässä näkyy seuraavaa:
 1 6  1 SURVO 84C EDITOR Tue Apr 23 15:35:43 1991         D:\SUOPAS\ 120  80 0
   1 *
   2 *
   3 *
   4 *TIME _
   5 *
   6 *
   7 *

Aktivoimme TIME-komennon napilla ESC ja saamme päiväyksen:
 1 6  1 SURVO 84C EDITOR Tue Apr 23 15:35:57 1991         D:\SUOPAS\ 120  80 0
   1 *
   2 *
   3 *
   4 *TIME Tue Apr 23 15:35:57 1991
   5 *
   6 *
   7 *

Siirrämme nyt kohdistimen rivin 4 alkuun napilla HOME ja poistamme 16 ensimmäistä merkkiä painamalla nappia DELETE 16 kertaa:
 1 1  1 SURVO 84C EDITOR Tue Apr 23 15:36:15 1991         D:\SUOPAS\ 120  80 0
   1 *
   2 *
   3 *
   4 *15:35:57 1991
   5 *
   6 *
   7 *

Lopuksi siirrämme kohdistinta 8 askelta oikealle nuolinapilla ja pyyhimme vuosiluvun (1991) napilla ctrl-END, jolloin jäljelle jää pelkkä kellonaika:
 1 9  1 SURVO 84C EDITOR Tue Apr 23 15:36:27 1991         D:\SUOPAS\ 120  80 0
   1 *
   2 *
   3 *
   4 *15:35:57_
   5 *
   6 *
   7 *

Tässä on toistaiseksi kaikki mitä haluamme määritellä sukroksi AIKA. Lopetamme siis sukron määrittelyn painamalla nappeja PREFIX ja T . Tällöin alariville tulee kysymys:

   Sucro functions: E=End of definition, C=Control codes, R=Repeat ? _
Painamalla nappia E tiedosto AIKA.TUT sulkeutuu ja kysymysteksti häviää. Myös sukron tasoa osoittava 1 otsikkorivin edestä poistuu. Ollaan siis takaisin tavallisessa kirjoitustilassa, mutta koko edellä kuvattu toiminta on tallentunut sukroksi AIKA.

Saatamme kokeilla sen toimintaa välittömästi aktivoimalla komennon /AIKA seuraavasti:
 1 6  1 SURVO 84C EDITOR Tue Apr 23 15:37:02 1991         D:\SUOPAS\ 120  80 0
   1 *
   2 *
   3 *
   4 *15:35:57
   5 */AIKA_
   6 *
   7 *

Tallettamamme toiminnat toistuvat ja saamme tuloksen seuraavalle riville 6:
 1 9  1 SURVO 84C EDITOR Tue Apr 23 15:37:02 1991         D:\SUOPAS\ 120  80 0
   1 *
   2 *
   3 *
   4 *15:35:57
   5 */AIKA
   6 *15:37:02_
   7 *

Sukro aktivoitiin siis samoin kuin mikä tahansa Survon komento. Nimen eteen tuli vain lisätä kauttaviiva / .

Sukroa saatetaan nyt jatkaa ja kehitellä ottamalla siitä sukrokielinen listaus toimituskenttään TUTLOAD-komennolla:
  13  1 SURVO 84C EDITOR Tue Apr 23 15:37:56 1991         D:\SUOPAS\ 120  80 0
   1 *
   2 *
   3 *
   4 *15:35:57
   5 */AIKA
   6 *15:37:02_
   7 *
   8 *TUTLOAD AIKA_
   9 *{R}
  10 *TIME {act}{home}{del16}{r8}{erase}{end}
  11 *

Sukrokielinen ohjelma näkyy tässä riveillä 9 ja 10. Koodia on helppo tulkita. Kaikki sukron teon aikana kirjoitettu teksti (komento "TIME ") näkyy sellaisenaan. Erikoisnäppäimillä, jotka eivät jätä kirjoitettua jälkeä, on omat aaltosuluin varustetut koodisanansa.
     Esimerkissämme on ensimmäisenä koodisana {R}, joka vastaa rivinsiirtoa. Koodit {act}, {home} ja {erase} tarkoittavat nappeja ESC, HOME ja ctrl-END. Koodi {del16} merkitsee napin DELETE 16-kertaista painallusta ja {r8} nuolta oikealle 8 kertaa. Esim. jälkimmäisen saisi merkitä myös muodossa {r}{r}{r}{r}{r}{r}{r}{r}, mutta ymmärrettävästi sukrokääntäjä pyrkii käyttämään lyhyimpiä mahdollisia esitystapoja. Sukron listaus päättyy aina koodisanaan {end} .

Sukro-ohjelma kertoo näin yksikäsitteisesti koko työn kulun kohdistimen liikkeitä myöten. Ohjelman listausta on lupa muuttaa ja esim. lisätä siihen uusia piirteitä.
     Teemme nyt toisen sukron nimeltä TUNTI edellisen avulla muuttamalla ohjelmaa siten, että myös minuutit ja sekunnit pyyhitään tuloksesta, jolloin vain tuntia koskeva merkintä jää jäljelle. Tämä tapahtuu yksinkertaisesti muuttamalla koodi {r8} (=8 askelta oikealle) muotoon {r2} (=2 askelta oikealle). Tällöin kohdistin siirtyy sarakkeeseen 3 kentässä ja {erase} poistaa koko loppurivin tuntiosoituksen perästä.

Muutamme myös rivillä 8 olevan komennon muotoon TUTSAVE TUNTI ja aktivoimme sen:
  14  1 SURVO 84C EDITOR Tue Apr 23 15:39:31 1991         D:\SUOPAS\ 120  80 0
   1 *
   2 *
   3 *
   4 *15:35:57
   5 */AIKA
   6 *15:37:02_
   7 *
   8 *TUTSAVE TUNTI_
   9 *{R}
  10 *TIME {act}{home}{del16}{r2}{erase}{end}
  11 *

Kun /TUNTI kirjoitetaan rivin 11 alkuun ja aktivoidaan, riville 12 ilmaantuu tämänhetkinen tuntilukema:
   3  1 SURVO 84C EDITOR Tue Apr 23 15:40:18 1991         D:\SUOPAS\ 120  80 0
   1 *
   2 *
   3 *
   4 *15:35:57
   5 */AIKA
   6 *15:37:02_
   7 *
   8 *TUTSAVE TUNTI
   9 *{R}
  10 *TIME {act}{home}{del16}{r2}{erase}{end}
  11 */TUNTI
  12 *15_
  13 *

Näytteenä huomattavasti laajemmasta kehitelmästä näytämme, miten TUNTI-sukro saadaan edelleen muutetuksi sukroksi HETKI, joka luonnehtii vuorokaudenaikaa selväkielisin lausein "Nyt on aamu.", "Nyt on iltapäivä." jne. Esim. tuntiosoituksen ollessa 15, sukron pitäisi lausua: "Nyt on iltapäivä.".
     Tämä merkitsee, että sukron tulisi tehdä päätelmiä kenttään ilmestyneiden tulosten pohjalta. Tällaisia tilanteita varten sukro voi poimia tietoa esim. toimituskentästä tai käyttäjältä (vastauksena erilaisiin kysymyksiin) ja tallettaa tiedot erityiseen sukromuistiin, josta aikaisemmin käytettiin nimitystä sukropino (tutstack). Esim. se sana tai luku, jota kohdistin parhaillaan osoittaa, saadaan luetuksi tähän muistiin ja sen ensimmäiseen muistipaikkaan W1 koodisanalla {save word W1} .
     Teemme nyt mainitun laajennuksen tallettamalla nykytunnin paikkaan W1 ja tutkimme sukrokielen ehdollisilla käskyillä, mikä on tilanne. Varustamme ohjelman myös selitysriveillä. Ohjelma näyttää TUTSAVE-komenolla talletettuna seuraavalta:
  14  1 SURVO 84C EDITOR Tue Apr 23 15:52:00 1991         D:\SUOPAS\ 120  80 0
   8 *TUTSAVE HETKI_
   9 *{R}
  10 /
  11 / Kirjoitetaan tämänhetkinen tunti (esim. 17) rivin alkuun:
  12 *TIME {act}{home}{del16}{r2}{erase}
  13 /
  14 / Siirretään kohdistin rivin alkuun:
  15 *{home}
  16 / Kohdistin koskettaa tuntimerkintää (17)
  17 /
  18 / Talletetaan sana sukromuistiin (W1=17):
  19 *{save word W1}
  20 /
  21 / Kirjoitetaan lauseen alku:
  22 *Nyt on
  23 /
  24 / Haaraudutaan tunnin mukaan:
  25 - if W1 > 18 then goto Ilta
  26 - if W1 > 12 then goto Iltapäivä
  27 - if W1 = 12 then goto Keskipäivä
  28 - if W1 > 5 then goto Aamu
  29 /
  30 / Jos mikään ylläolevista ei päde, on 1 <= W1 <= 5 .
  31 / Tällöin jatketaan kirjoittamalla " yö" ja hypätään loppuun:
  32 * yö{goto L}
  33 /
  34 / Jos W1 > 18, on hypätty kohtaan "Ilta".
  35 / Kirjoitetaan " ilta" ja siirrytään loppuun:
  36 + Ilta:  ilta{goto L}
  37 /
  38 / Muut vaihtoehdot käsitellään vastaavasti:
  39 + Iltapäivä:  iltapäivä{goto L}
  40 + Keskipäivä:  keskipäivä{goto L}
  41 + Aamu:  aamu
  42 /
  43 / Kaikki vaihtoehdot vievät kohtaan L.
  44 / Lopetetaan lause pisteeseen.
  45 + L: .{end}
  46 *

Sukro-ohjelman listauksessa käytetään kontrollisaraketta eri tavoin. Esim. rivit, joilla on / kontrollisarakkeessa, ovat pelkkiä selityksiä varten. Ne eivät vaikuta sukron toimintaan vaan ainoastaan helpottavat ohjelman lukemista. Ehdollisia if-käskyjä sisältävät rivit alkavat merkillä - ja rivit, joihin viitataan esim. goto-käskyissä, alkavat merkillä + .
     Koko ohjelma tallentuu TUTSAVE-komennolla HETKI.TUT-tiedostoon tiivistetyssä muodossa, mutta se palautuu takaisin luettavaan muotoon vastaavalla TUTLOAD-komennolla.

Tiedoston HETKI.TUT koko on vain 820 tavua. Jos selitysrivit jätettäisiin pois, tiedosto supistuisi 241 tavuun. Tulkkiperiaatteella toimivien ohjelmien heikkoutena on usein se, että esim. koodin seassa olevat selitykset saattavat hidastaa ohjelman suoritusta. Näin ei tapahdu sukroissa, sillä kääntäjä siirtää ohjelmaa talletettaessa kaikki selitysrivit tiedoston loppuun. Kustakin kommenttirivistä jää vain yksi tavu asianomaiselle paikalle.

Vertailun vuoksi vastaava toiminta on ohjelmoitu Survon komennoksi C-kielellä. Sen listaus näyttää seuraavalta:

          #include <stdio.h> 
          #include <stdlib.h> 
          #include <string.h> 
          #include <time.h> 
          #include "\e1\survo.h"
          #include "\e1\survoext.h"

          main(argc,argv)
          int argc; char *argv[];
                  {
                  long aika;
                  int tunti;
                  char lause[50];
                  int rivi;

                  s_init(argv[1]);
                  time(&aika);
                  tunti=atoi(ctime(&aika)+11);
                  strcpy(lause,"Nyt on ");
                  if (tunti>18) strcat(lause,"ilta.");
                  else if (tunti>12) strcat(lause,"iltapäivä.");
                  else if (tunti==12) strcat(lause,"keskipäivä.");
                  else if (tunti>5) strcat(lause,"aamu.");
                  else strcat(lause,"yö.");
                  rivi=r1+r;
                  edwrite(space,rivi,1);
                  edwrite(lause,rivi,1);
                  }

Listaus on ehkä lyhyempi, koska kommentit puuttuvat, mutta lopullinen ohjelma käännettynä on yli 16000 tavua, koska C-kääntäjä joutuu liittämään mukaan erilaisia kirjastoaliohjelmia. Sukroilla taustana oleva Survo-järjestelmä tarjoaa suoraan vastaavat palvelut eikä esim. syöttö- ja tulostusaliohjelmia tarvitse sisällyttää sukron ohjelmatiedostoon.

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