Semantyka i weryfikacja programów/Ćwiczenia 7: Różnice pomiędzy wersjami

Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania
Arturas (dyskusja | edycje)
Dorota (dyskusja | edycje)
Nie podano opisu zmian
Linia 38: Linia 38:
</math>
</math>


Pętla <math> \mathbf{repeat}\,\, i \,\,\mathbf{until}\,\, b </math> polega na wykonaniu instrukcji ''i'', a następnie wyliczeniu warunku logicznego ''b''. Jeśli warunek jest prawdziwy wykonanie pętli kończy się, w przeciwnym razie powracamy do wykonania instrukcji ''i''.
Pętla <math> \mathbf{repeat}\,\, i \,\,\mathbf{until}\,\, b </math> polega na wykonaniu instrukcji ''i'', a następnie wyliczeniu warunku logicznego ''b''. Jeśli warunek jest prawdziwy, wykonanie pętli kończy się, w przeciwnym razie powracamy do wykonania instrukcji ''i''.
}}
}}


Powyższy język to tak naprawdę Tiny z wykładu rozszerzony o jedną
Powyższy język to tak naprawdę TINY z wykładu rozszerzony o jedną
konstrukcję: pętlę '''repeat'''. Spróbuj wykonać to ćwiczenie nie
konstrukcję: pętlę '''repeat'''. Spróbuj wykonać to ćwiczenie nie
sięgając do notatek z wykładu. Jeśli napotkasz trudności, odkrywaj
sięgając do notatek z wykładu. Jeśli napotkasz trudności, odkrywaj
Linia 54: Linia 54:
Zaczynamy jak zwykle od opisu dziedzin semantycznych. Nie przejmujemy
Zaczynamy jak zwykle od opisu dziedzin semantycznych. Nie przejmujemy
się na razie szczegółami związanymi z konstrukcjami stałopunktowymi
się na razie szczegółami związanymi z konstrukcjami stałopunktowymi
oraz umieszczeniem pineski we właściwych dziedzinach. Zakładamy, że
oraz umieszczeniem pinezki we właściwych dziedzinach. Zakładamy, że
wszystkie zmienne są zainicjowane na zero.  
wszystkie zmienne są zainicjowane na zero.  


Linia 95: Linia 95:
jest wartość stałej liczbowej.  
jest wartość stałej liczbowej.  


Rozpocznijmy od funkcji semantycznej dla wyrażeń. Musimy zdefioniować
Rozpocznijmy od funkcji semantycznej dla wyrażeń. Musimy zdefiniować
znaczenie (wartość) wyrażenia <math>e</math> w pewnym stanie <math>s</math>. Ową wartość
znaczenie (wartość) wyrażenia <math>e</math> w pewnym stanie <math>s</math>. Ową wartość
zapisujemy jako <math>\mathcal{E} [\![e]\!] s</math>, czyli wartość funkcji E zastosowanej do
zapisujemy jako <math>\mathcal{E} [\![e]\!] s</math>, czyli wartość funkcji E zastosowanej do
Linia 104: Linia 104:
Funkcje semantyczne definiujemy dla każdej postaci wyrażenia,
Funkcje semantyczne definiujemy dla każdej postaci wyrażenia,
odpowiadając na standardowe pytania:
odpowiadając na standardowe pytania:
# Co jest wartością wyrażenia <math>x</math> w stanie <math>s</math>, Odpowiedź: wartość
# Co jest wartością wyrażenia <math>x</math> w stanie <math>s</math>? Odpowiedź: wartość
zmiennej <math>x</math> w tym stanie, czyli wartość uzyskana przez zastosowanie
zmiennej <math>x</math> w tym stanie, czyli wartość uzyskana przez zastosowanie
funkcji <math>s</math> do identyfikatora <math>x</math>. Zapisujemy to następująco
funkcji <math>s</math> do identyfikatora <math>x</math>. Zapisujemy to następująco:


<center><math>\mathcal{E} [\![x]\!] s = s (x)</math></center>
<center><math>\mathcal{E} [\![x]\!] s = s (x)</math></center>


Często będziemy powijać nawiasy przy aplikacji funkcji pisząc po
Często będziemy pomijać nawiasy przy aplikacji funkcji pisząc po
prostu <math>s\,x</math> zamiast <math>s(x)</math>. To samo można zapisać stosując notację
prostu <math>s\,x</math> zamiast <math>s(x)</math>. To samo można zapisać stosując notację
"lambda":  
"lambda":  
Linia 168: Linia 168:


{{cwiczenie| 4|cw4|
{{cwiczenie| 4|cw4|
O pętli for można jednak myśleć jeszcze inaczej. Można wymagać, aby wszelkie zmiany wartości zmiennej sterującej <math>x</math> wewnątrz wykonania pętli nie miały wpływu na liczbę iteracji tej pętli. Przykładowo przy semantyce z poprzedniego zadania pętla:
O pętli '''for''' można jednak myśleć jeszcze inaczej. Można wymagać, aby wszelkie zmiany wartości zmiennej sterującej <math>x</math> wewnątrz wykonania pętli nie miały wpływu na liczbę iteracji tej pętli. Przykładowo przy semantyce z poprzedniego zadania pętla:
  '''for''' x :<nowiki>=</nowiki> 1 '''to''' 10 '''do'''  
  '''for''' x :<nowiki>=</nowiki> 1 '''to''' 10 '''do'''  
   x:<nowiki>=</nowiki> x + 1;
   x:<nowiki>=</nowiki> x + 1;
   y:<nowiki>=</nowiki> y + x;
   y:<nowiki>=</nowiki> y + x;
wykonuje się pięć razy, a zmienna y jest zwiększana łącznie o 2+4+6+8+10. Jeśli uznamy, że zmiany zmiennej x wewnątrz pętli nie wpływają na liczbę iteracji, to pętla wykona się 10 razy, a zmienna y zostanie zwiększona o 2+3+4+5+6+7+8+9+10+11.  
wykonuje się pięć razy, a zmienna <math>y</math> jest zwiększana łącznie o 2+4+6+8+10. Jeśli uznamy, że zmiany zmiennej <math>x</math> wewnątrz pętli nie wpływają na liczbę iteracji, to pętla wykona się 10 razy, a zmienna <math>y</math> zostanie zwiększona o 2+3+4+5+6+7+8+9+10+11.  
Zdefiniuj taką semantykę.
Zdefiniuj taką semantykę.
}}
}}

Wersja z 14:55, 29 wrz 2006

Semantyka bezpośrednia instrukcji. Konstrukcje iteracyjne.

Pętle while i repeat

Ćwiczenie 1

Zdefiniuj semantykę denotacyjną następującego języka:

n::=1|0|1|

x::=(identyfikatory)

e::=n|x|e1+e2

b::=e1=e2|𝐧𝐨𝐭b|b1𝐨𝐫b2

i::=x:=e|i1;i2|𝐢𝐟b𝐭𝐡𝐞𝐧i1𝐞𝐥𝐬𝐞i2|𝐬𝐤𝐢𝐩|𝐰𝐡𝐢𝐥𝐞b𝐝𝐨i|𝐫𝐞𝐩𝐞𝐚𝐭i𝐮𝐧𝐭𝐢𝐥b

Pętla 𝐫𝐞𝐩𝐞𝐚𝐭i𝐮𝐧𝐭𝐢𝐥b polega na wykonaniu instrukcji i, a następnie wyliczeniu warunku logicznego b. Jeśli warunek jest prawdziwy, wykonanie pętli kończy się, w przeciwnym razie powracamy do wykonania instrukcji i.

Powyższy język to tak naprawdę TINY z wykładu rozszerzony o jedną konstrukcję: pętlę repeat. Spróbuj wykonać to ćwiczenie nie sięgając do notatek z wykładu. Jeśli napotkasz trudności, odkrywaj kolejne elementy poniższego opisu.

Kategorie składniowe występujące w tym języku to:

  • wyrażenia Exp
  • wyrażenia logiczne BExp
  • instrukcje Stmt
  • oraz, jak zwykle, stałe liczbowe Num

Zaczynamy jak zwykle od opisu dziedzin semantycznych. Nie przejmujemy się na razie szczegółami związanymi z konstrukcjami stałopunktowymi oraz umieszczeniem pinezki we właściwych dziedzinach. Zakładamy, że wszystkie zmienne są zainicjowane na zero.

Użyjemy elementarnych dziedzin z wykładu:

  • Int = ..., -1, 0, 1, ... zawierający denotacje stałych

liczbowych

  • Bool = {tt}, {ff} zawierający wartości logiczne
  • Var zawierający wszystkie dozwolone identyfikatory

Przypomnijmy, że wartość wyrażenia arytmetycznego e zależy od

Wartości te są "pamiętane" w stanie, który jest funkcją ze zbioru Var w zbiór Int. Zbiór wszystkich stanów to:

State=VarInt

Zdefiniujmy następnie niezbędne funkcje semantyczne.

  • Dla wyrażeń mamy
Parser nie mógł rozpoznać (błąd składni): {\displaystyle \mathcal{E} & : & \mathrm Exp \rightarrow \mathrm State \rightarrow \mathrm Int }
  • Dla wyrażeń logicznych:
Parser nie mógł rozpoznać (błąd składni): {\displaystyle \mathcal{B} & : & \mathrm BExp \rightarrow \mathrm State \rightarrow \mathrm Bool }
  • Dla instrukcji:
Parser nie mógł rozpoznać (błąd składni): {\displaystyle \mathcal{I} & : & \mathrm Stmt \rightarrow \mathrm State \rightarrow \mathrm State }
  • Oraz oczywistą funkcję dla stałych całkowitych:
Parser nie mógł rozpoznać (błąd składni): {\displaystyle \mathcal{Z} & : & \mathrm Num \rightarrow \mathcal{Z} }

Funkcji {Z} nie definiujemy, przyjmując jak zwykle, że jej wynikiem jest wartość stałej liczbowej.

Rozpocznijmy od funkcji semantycznej dla wyrażeń. Musimy zdefiniować znaczenie (wartość) wyrażenia e w pewnym stanie s. Ową wartość zapisujemy jako [[e]]s, czyli wartość funkcji E zastosowanej do dwóch argumentów: wyrażenia e oraz stanu s. Przypomnijmy, że taka "dziwna" notacja z nawiasami służy oddzieleniu składni od elementów z metajęzyka.

Funkcje semantyczne definiujemy dla każdej postaci wyrażenia, odpowiadając na standardowe pytania:

  1. Co jest wartością wyrażenia x w stanie s? Odpowiedź: wartość

zmiennej x w tym stanie, czyli wartość uzyskana przez zastosowanie funkcji s do identyfikatora x. Zapisujemy to następująco:

[[x]]s=s(x)

Często będziemy pomijać nawiasy przy aplikacji funkcji pisząc po prostu sx zamiast s(x). To samo można zapisać stosując notację "lambda":

Parser nie mógł rozpoznać (nieznana funkcja „\l”): {\displaystyle \mathcal{E} [\![x]\!] = \l s \in \mathrm State.s (x)}

Pętla for

Ćwiczenie 2

Rozszerzmy język z poprzedniego zadania o instrukcję:

i::=𝐟𝐨𝐫x:=e1𝐭𝐨e2𝐝𝐨i

Wykonanie takiej pętli polega na:

  1. Wyliczeniu wartości n wyrażenia e1.
  2. Przypisaniu wartości n na zmienną x.
  3. Wyliczeniu wartości m wyrażenia e2.
  4. Jeśli x>m, to pętla kończy się.
  5. W przeciwnym razie:
    • Wykonujemy instrukcję i.
    • Zwiększamy zmienną x o 1.
    • Powracamy do punktu 3.

Zauważmy, że wyrażenie e1 jest tu wyliczane tylko raz, ale e2 oblicza się przy każdym obrocie pętli.

Rozwiązanie

{{{3}}}

Ćwiczenie 3

Zmieńmy semantykę instrukcji for z poprzedniego zadania tak, aby oba wyrażenia obliczały się tylko raz. Tym razem wyliczenie pętli polega na:

  1. Wyliczeniu wartości n wyrażenia e1.
  2. Przypisaniu wartości n na zmienną x.
  3. Wyliczeniu wartości m wyrażenia e2.
  4. Jeśli x>m, to pętla kończy się.
  5. W przeciwnym razie:
    • Wykonujemy instrukcję i.
    • Zwiększamy zmienną x o 1.
    • Powracamy do punktu 4.

Rozwiązanie

{{{3}}}

Ćwiczenie 4

O pętli for można jednak myśleć jeszcze inaczej. Można wymagać, aby wszelkie zmiany wartości zmiennej sterującej x wewnątrz wykonania pętli nie miały wpływu na liczbę iteracji tej pętli. Przykładowo przy semantyce z poprzedniego zadania pętla:

for x := 1 to 10 do 
  x:= x + 1;
  y:= y + x;

wykonuje się pięć razy, a zmienna y jest zwiększana łącznie o 2+4+6+8+10. Jeśli uznamy, że zmiany zmiennej x wewnątrz pętli nie wpływają na liczbę iteracji, to pętla wykona się 10 razy, a zmienna y zostanie zwiększona o 2+3+4+5+6+7+8+9+10+11. Zdefiniuj taką semantykę.

Rozwiązanie

{{{3}}}

Ćwiczenie 5

W języku C pętla for ma następującą postać: i::=𝐟𝐨𝐫(i1;b;i2)i3

Jej wykonanie polega na:

  1. Wykonaniu instrukcji i1.
  2. Wyliczeniu wartości wyrażenia b.
  3. Jeśli wyrażenie wylicza się do fałszu, to pętla kończy się.
  4. W przeciwnym razie:
    • Wykonujemy instrukcję i3.
    • Wykonujemy instrukcję i2.
    • Powracamy do punktu 2.

Rozwiązanie

{{{3}}}