2. kodused ülesanded

Üldinfo

Lahenduste esitamise tähtaeg on 25. 04, kell 11.59. Lahendused saata mailiga varmo@cs.ut.ee; subjektiks peab olema pk-kodu-2. Kokku on ülesannete eest võimalik saada kuni 70 punkti. Hilinenud lahenduste korral väheneb punkti summa 10% iga hilinenud päeva kohta. Näiteks, kui lahendus on väärt 50 punkti, aga jõuab minuni 26. 04 kell 12.00 (so. kaks päeva hiljem), siis on tegelik punktisumma 50 * 0.9^2 = 41.

Vormistamisest

Kõigi ülesannete lahendused vormistada eraldi Scheme failidena, millede nimed on kujul pk-kodu-2-n.s, kus n on ülesande number (näiteks viienda ülesande lahendus on failis nimega pk-kodu-2-5.s). Faili algusse lisada kommentaaridena kõigi rühmaliikmete nimed (rühmas võib olla max. 5 liiget) ja maili-aadressid. Kõigi ülesannete lahendustes ümbritseda see koodi osa, mida modifitseerisite selgesti eristatavate kommentaaridega.

Ülesanded

  1. [EOPL 5.5.5; 6.1.1] (20p) Aluseks kasutada loengus esitatud "call-by-value" parameetrite edastamisega ning kaudsete massiividega interpretaatorit loeng13-1.ss.

    Laiendame keelt erivormidega:
          <form> ::= define <var> = <exp>
                   | definearray <var> [<exp>]
                   | <exp>
    
            define (var exp)
            definearray (var len-exp)
    
    
    Modifitseeri 'read-eval-print' tsüklit selliselt, et ta loeb sisse erivormi ja sõltuvalt sellest kas tegemist avaldisega või definitsiooniga ta kas väärtustab selle avaldise (ning trükib välja tulemuse) või lisab vastava definitsiooni globaalsesse keskkonda (init-env). Kui defineeritav muutuja on juba globaalses keskkonnas seotud, siis omistatakse antud seosele uus väärtus. Definitsioonid ei ole rekursiivsed; ehk kui defineeritava muutujaga sama nimega muutuja esineb ka defineerivas avaldises, siis viitab see antud muutuja varajasemale seosele.

    --> "define x = 3"
    --> "x"
    3
    --> "define x = +(x, 2)"
    --> "x"
    5
    --> "definearray x [2]"
    --> "begin
           x[0] := 1;
           x[1] := +(x[0], 5);
           x[1]
         end"
    6
    

  2. [EOPL 5.5.7] (10p) Loengus esitatud interpretaator loeng11-2.ss lisas keelde omistamise selliselt, et omistada on võimalik kõigile muutujatele. Alternatiivne variant on lubada keeles samaaegselt kasutada nii muudetavaid kui ka mittemuudetavid muutujate sidumisi:

    Denoted Value = Cell(Expressed Value) + Expressed Value
    

    Sellisel juhul saab omistada ainult muudetavatele muutujatele.

    Lisame keelde uue lokaalsete definitsioonide konstruktsiooni, mille abil saab defineerida muudetavaid muutujaid:

      <exp> ::= letmutable <decls> in <exp>        letmutable (decls body)
    

    Modifitseeri interpretaatorit loeng11-2.ss selliselt, et tavalised let-avaldistega defineeritavad muutujad on mittemuudetavad ning letmutable-avaldisega defineeritavad muutujad on muudevad.

    Näiteks:

    --> "letmutable x = 1 in
         let y = 2 in
         begin
           x := +(y, 3)
         end"
    5
    --> "letmutable x = 1 in
         let y = 2 in
         begin
           y := +(x, 3)
         end"
    Can't mutate the immutable variable: y 
    

  3. [EOPL 5.7.8] (10p) Aluseks võtta loengus toodud interpretaator loeng11-2.ss.

    Lisada keelde uus konstruktsioon, mis lubab dünaamiliselt omistada mitmele muutujale korraga:

      <exp> ::= letdynamic <decls> in <exp>        letdynamic (decls body)
    

    Näiteks:

    --> "let x = 1; y = 2 in
         let p = proc (x, a) +(a, *(x, y)) in
         letdynamic
             x = +(x, y);
             y = +(x, 3)
         in p(x, y)"
    16
    --> "let x = 1; y = 2 in
         let p = proc (x, a) +(a, *(x, y)) in
         p(x, y)"
    4
    --> "let x = 4 in
         let p = proc (y) +(x, y) in
         +(letdynamic x = 7 in p(1), p(2))"
    14
    

  4. [EOPL 6.3.1] (10p) Aluseks võtta loengus esitatud "call-by-reference" parameetrite edastamisega ning kaudsete massiividega interpretaator loeng13-3.ss.

    Modifitseerida interpretaatorit selliselt, et protseduuri parameetreid edastatakse "call-by-value-result".

    --> "define swap = proc (x, y)
                  let temp = 0 in
                  begin temp := x; x := y; y := temp end"
    --> "define c = 3"
    --> "let b = 4 in
         begin
           swap(c, b);
           b
         end"
    3
    --> "c"
    4
    --> "define swap2 = proc (x, y)
             begin
               x := +(x, y); y := -(x, y); x := -(x, y)
             end"
    --> "let b = 1; c = 2 in
          begin swap2(b, c); c end"
    1
    --> "let b = 1
         in begin swap2(b, b); b end"
    1
    

  5. [EOPL 6.6.1] (10p) Aluseks võtta loengus esitatud "call-by-value" parameetrite edastamisega ning kaudsete massiividega interpretaator loeng13-1.ss (või esimeses ülesandes realiseeritud inetrpretaator, mis sellel baseerus).

    Modifitseerida interpretaatorit selliselt, et ta toetaks mittekohustuslike (optional) parameetreid. Protseduuri formaalsete parameetrite süntaks on:

       <varlist> ::= ()
                   | (<vars> {,<keydecl>}* )
                   | (<keydecls>)
      <keydecls> ::= <keydecl> {,<keydecl>}*
       <keydecl> ::= :<var> = <exp>                 keydecl (var exp)
    

    Mittekohustuslike parameetritega protseduuride väljakutsel väärtustatakse kõigepealt mittekohustuslike parameetrite vaikimisi definitsioonid (selleks kasutades keskonda, mis kehtis protseduuri defineerimise hetkel). Seejärel, kui vastavat parameetrit tegelike argumentide listis pole, kasutatakse saadud vaikimisi väärtust; kui aga on, siis kasutatakse tegeliku argumendi väärtust. Kui protseduuri väljakutsel on ära jäetud kohustuslik parameeter, siis on tulemuseks täitmisaegne viga.

    --> "(proc (x, :a = 1) +(x, a))(100)"
    101
    --> "let y = 3
         in (proc (x, :a = 1, :b = +(2, y))
                  +(x, +(a, b)))
            (100, 10)"
    115
    

  6. [EOPL 6.6.3] (10p) Aluseks võtta eelmises ülesandes realiseeritud interpretaator.

    Modifitseerida interpretaatorit selliselt, et ta toetaks võtmesõnade abil edasiantavaid parameetreid. Operandide süntaks on järgmine:

      <operands> ::= ()
                   | (<exps> {,<keydecl>}* )
                   | (<keydecls>)
          <exps> ::= <exp> {,<exp>}*
    

    Näiteks:

    --> "(proc (x, y) -(x, y))(:y = 3, :x = 2)"
    -1
    --> "(proc (x, :a = 1, :b = +(2, 3))
                        +(x, +(a, b)))
         (100, :b = 2)"
    103
    

Varmo Vene