Semantyka i weryfikacja programów/Ćwiczenia 3: Różnice pomiędzy wersjami
Nie podano opisu zmian |
Nie podano opisu zmian |
||
Linia 20: | Linia 20: | ||
==== Rozwiązanie ==== | ==== Rozwiązanie ==== | ||
<div class="mw-collapsible mw-made=collapsible mw-collapsed"><div class="mw-collapsible-content" style="display:none"> | |||
Przypomnijmy składnię wyrażeń boolowskich i arytmetycznych | Przypomnijmy składnię wyrażeń boolowskich i arytmetycznych | ||
Linia 55: | Linia 57: | ||
Chcemy, aby tranzycje wyrażen wyglądały następująco: | Chcemy, aby tranzycje wyrażen wyglądały następująco: | ||
<math> | |||
e, s \longrightarrow n | e, s \longrightarrow n | ||
\quad \quad \quad | \quad \quad \quad | ||
Linia 78: | Linia 80: | ||
Np. dla instrukcji pętli będziemy mieć następujące reguły: | Np. dla instrukcji pętli będziemy mieć następujące reguły: | ||
<math> | |||
\frac{b, s \,\longrightarrow\, \mathbf{true} \quad \quad I; \mathbf{while}\, b \,\mathbf{do}\, I, s \,\longrightarrow\, s'} | \frac{b, s \,\longrightarrow\, \mathbf{true} \quad \quad I; \mathbf{while}\, b \,\mathbf{do}\, I, s \,\longrightarrow\, s'} | ||
{\mathbf{while}\, b \,\mathbf{do}\, I, s \,\longrightarrow\, s'} | {\mathbf{while}\, b \,\mathbf{do}\, I, s \,\longrightarrow\, s'} | ||
</math> | </math> | ||
<math> | |||
\frac{b, s \,\longrightarrow\, \mathbf{true}} | \frac{b, s \,\longrightarrow\, \mathbf{true}} | ||
{\mathbf{while}\, b \,\mathbf{do}\, I, s \,\longrightarrow\, s} | {\mathbf{while}\, b \,\mathbf{do}\, I, s \,\longrightarrow\, s} | ||
Linia 92: | Linia 94: | ||
Zacznijmy od stalych arytmetycznych i boolowskich: | Zacznijmy od stalych arytmetycznych i boolowskich: | ||
<math> | |||
n, s \,\longrightarrow\, n | n, s \,\longrightarrow\, n | ||
\quad \quad | \quad \quad | ||
Linia 100: | Linia 102: | ||
Operatory arytmetyczne definiujemy następująco: | Operatory arytmetyczne definiujemy następująco: | ||
<math> | |||
\frac{e_1, s \,\longrightarrow\, n_1 \quad \quad | \frac{e_1, s \,\longrightarrow\, n_1 \quad \quad | ||
e_2, s \,\longrightarrow\, n_2 \quad \quad | e_2, s \,\longrightarrow\, n_2 \quad \quad | ||
Linia 119: | Linia 121: | ||
arytmnetycznych, oraz dla spójników logicznych: | arytmnetycznych, oraz dla spójników logicznych: | ||
<math> | |||
\frac{b_1, s \,\longrightarrow\, l_1 \quad \quad | \frac{b_1, s \,\longrightarrow\, l_1 \quad \quad | ||
b_2, s \,\longrightarrow\, l_2 \quad \quad | b_2, s \,\longrightarrow\, l_2 \quad \quad | ||
Linia 128: | Linia 130: | ||
Oto inny wariant, reguły lewo-stronne (ponieważ rozpoczynamy od ''lewego'' koniunktu): | Oto inny wariant, reguły lewo-stronne (ponieważ rozpoczynamy od ''lewego'' koniunktu): | ||
<math> | |||
\frac{b_1, s \,\longrightarrow\, \mathbf{true}} | \frac{b_1, s \,\longrightarrow\, \mathbf{true}} | ||
{b_1 \land b_2, s \,\longrightarrow\, \mathbf{true}} | {b_1 \land b_2, s \,\longrightarrow\, \mathbf{true}} | ||
Linia 141: | Linia 143: | ||
Wreszcie rozważmy kombinację obydwu semantyk (reguły ''równoległe''): | Wreszcie rozważmy kombinację obydwu semantyk (reguły ''równoległe''): | ||
<math> | |||
\frac{b_1, s \,\longrightarrow\, \mathbf{true}} | \frac{b_1, s \,\longrightarrow\, \mathbf{true}} | ||
{b_1 \land b_2, s \,\longrightarrow\, \mathbf{true}} | {b_1 \land b_2, s \,\longrightarrow\, \mathbf{true}} | ||
Linia 162: | Linia 164: | ||
są równoważne. | są równoważne. | ||
Reguły dla pozostałych spójników logicznych, dla | Reguły dla pozostałych spójników logicznych, dla | ||
negacji oraz dla instrukcji przypisania pozostawiamy jako proste ćwiczenie. | negacji oraz dla instrukcji przypisania pozostawiamy jako proste | ||
ćwiczenie. | |||
</div></div> | |||
Linia 221: | Linia 226: | ||
jest wstrzymame. | jest wstrzymame. | ||
<math> | |||
\frac{e_1, s \,\longrightarrow\, \mathtt{Blad}} | \frac{e_1, s \,\longrightarrow\, \mathtt{Blad}} | ||
{e_1 \leq e_2, s \,\longrightarrow\, \mathtt{Blad}} | {e_1 \leq e_2, s \,\longrightarrow\, \mathtt{Blad}} | ||
Linia 231: | Linia 236: | ||
Następnie, błąd w wyrażeniu powinien wstrzymać normalne wykonanie instrukcji: | Następnie, błąd w wyrażeniu powinien wstrzymać normalne wykonanie instrukcji: | ||
<math> | |||
\frac{b \,\longrightarrow\, \mathtt{Blad}} | \frac{b \,\longrightarrow\, \mathtt{Blad}} | ||
{\mathbf{if}\, b \,\mathbf{then}\, I_1 \,\mathbf{else}\, I_2, s \,\longrightarrow\, \mathtt{Blad}} | {\mathbf{if}\, b \,\mathbf{then}\, I_1 \,\mathbf{else}\, I_2, s \,\longrightarrow\, \mathtt{Blad}} | ||
</math> | </math> | ||
<math> | |||
\frac{b \,\longrightarrow\, \mathtt{Blad}} | \frac{b \,\longrightarrow\, \mathtt{Blad}} | ||
{\mathbf{while}\, b \,\mathbf{do}\, I, s \,\longrightarrow\, \mathtt{Blad}} | {\mathbf{while}\, b \,\mathbf{do}\, I, s \,\longrightarrow\, \mathtt{Blad}} | ||
</math> | </math> | ||
<math> | |||
\frac{e, s \,\longrightarrow\, \mathtt{Blad}} | \frac{e, s \,\longrightarrow\, \mathtt{Blad}} | ||
{x := e, s \,\longrightarrow\, \mathtt{Blad}} | {x := e, s \,\longrightarrow\, \mathtt{Blad}} | ||
Linia 248: | Linia 253: | ||
I wreszcie błąd powinien propagować się do kolejnych instrukcji: | I wreszcie błąd powinien propagować się do kolejnych instrukcji: | ||
<math> | |||
\frac{I_1, s \,\longrightarrow\, \mathtt{Blad}} | \frac{I_1, s \,\longrightarrow\, \mathtt{Blad}} | ||
{I_1;\, I_2, s \,\longrightarrow\, \mathtt{Blad}} | {I_1;\, I_2, s \,\longrightarrow\, \mathtt{Blad}} | ||
</math> | </math> | ||
<math> | |||
\frac{b, s \,\longrightarrow\, \mathbf{true} \quad \quad I_1, s \,\longrightarrow\, \mathtt{Blad}} | \frac{b, s \,\longrightarrow\, \mathbf{true} \quad \quad I_1, s \,\longrightarrow\, \mathtt{Blad}} | ||
{\mathbf{if}\, b \,\mathbf{then}\, I_1 \,\mathbf{else}\, I_2, s \,\longrightarrow\, \mathtt{Blad}} | {\mathbf{if}\, b \,\mathbf{then}\, I_1 \,\mathbf{else}\, I_2, s \,\longrightarrow\, \mathtt{Blad}} | ||
Linia 261: | Linia 266: | ||
</math> | </math> | ||
<math> | |||
\frac{b, s \,\longrightarrow\, \mathbf{true} \quad \quad I, s \,\longrightarrow\, \mathtt{Blad}} | \frac{b, s \,\longrightarrow\, \mathbf{true} \quad \quad I, s \,\longrightarrow\, \mathtt{Blad}} | ||
{\mathbf{while}\, b \,\mathbf{do}\, I, s \,\longrightarrow\, \mathtt{Blad}} | {\mathbf{while}\, b \,\mathbf{do}\, I, s \,\longrightarrow\, \mathtt{Blad}} | ||
Linia 302: | Linia 307: | ||
lub <math> \mathbf{continue} </math>. Oto odpowiednie reguły: | lub <math> \mathbf{continue} </math>. Oto odpowiednie reguły: | ||
<math> | |||
\mathbf{exit}, s \,\longrightarrow\, s, \mbox{było-}\mathbf{exit} | \mathbf{exit}, s \,\longrightarrow\, s, \mbox{było-}\mathbf{exit} | ||
\quad \quad | \quad \quad | ||
Linia 329: | Linia 334: | ||
Oczywiście beneficjentem tej informacji jest instrukcji <math> \mathbf{loop}\, </math>: | Oczywiście beneficjentem tej informacji jest instrukcji <math> \mathbf{loop}\, </math>: | ||
<math> | |||
\frac{I, s \,\longrightarrow\, s', \mbox{było-}\mathbf{exit}} | \frac{I, s \,\longrightarrow\, s', \mbox{było-}\mathbf{exit}} | ||
{\mathbf{loop}\, I, s \,\longrightarrow\, s'} | {\mathbf{loop}\, I, s \,\longrightarrow\, s'} | ||
Linia 348: | Linia 353: | ||
wywołania <math> \mathbf{continue} </math>: | wywołania <math> \mathbf{continue} </math>: | ||
<math> | |||
\frac{I, s \,\longrightarrow\, s' \quad \quad \mathbf{loop}\, I, s' \,\longrightarrow\, s''} | \frac{I, s \,\longrightarrow\, s' \quad \quad \mathbf{loop}\, I, s' \,\longrightarrow\, s''} | ||
{\mathbf{loop}\, I, s \,\longrightarrow\, s''} | {\mathbf{loop}\, I, s \,\longrightarrow\, s''} | ||
Linia 355: | Linia 360: | ||
'''Pytanie:''' czy potrzebujemy dodatkowo reguł postaci: | '''Pytanie:''' czy potrzebujemy dodatkowo reguł postaci: | ||
<math> | |||
\frac{I, s \,\longrightarrow\, s' \quad \quad \mathbf{loop}\, I, s' \,\longrightarrow\, s'', \mbox{było-}\mathbf{exit}} | \frac{I, s \,\longrightarrow\, s' \quad \quad \mathbf{loop}\, I, s' \,\longrightarrow\, s'', \mbox{było-}\mathbf{exit}} | ||
{\mathbf{loop}\, I, s \,\longrightarrow\, s'', \mbox{było-}\mathbf{exit}} | {\mathbf{loop}\, I, s \,\longrightarrow\, s'', \mbox{było-}\mathbf{exit}} | ||
Linia 375: | Linia 380: | ||
Oto odpowiednie reguły dla <math> \mbox{było-}\mathbf{exit} </math>: | Oto odpowiednie reguły dla <math> \mbox{było-}\mathbf{exit} </math>: | ||
<math> | |||
\frac{I_1, s \,\longrightarrow\, s', \mbox{było-}\mathbf{exit}} | \frac{I_1, s \,\longrightarrow\, s', \mbox{było-}\mathbf{exit}} | ||
{I_1;\, I_2, s \,\longrightarrow\, s', \mbox{było-}\mathbf{exit}} | {I_1;\, I_2, s \,\longrightarrow\, s', \mbox{było-}\mathbf{exit}} | ||
Linia 383: | Linia 388: | ||
</math> | </math> | ||
<math> | |||
\frac{b, s \,\longrightarrow\, \mathbf{true} \quad \quad I_1, s \,\longrightarrow\, s', \mbox{było-}\mathbf{exit}} | \frac{b, s \,\longrightarrow\, \mathbf{true} \quad \quad I_1, s \,\longrightarrow\, s', \mbox{było-}\mathbf{exit}} | ||
{\mathbf{if}\, b \,\mathbf{then}\, I_1 \,\mathbf{else}\, I_2, s \,\longrightarrow\, s', \mbox{było-}\mathbf{exit}} | {\mathbf{if}\, b \,\mathbf{then}\, I_1 \,\mathbf{else}\, I_2, s \,\longrightarrow\, s', \mbox{było-}\mathbf{exit}} | ||
Linia 391: | Linia 396: | ||
</math> | </math> | ||
<math> | |||
\frac{b, s \,\longrightarrow\, \mathbf{true} \quad \quad I, s \,\longrightarrow\, s', \mbox{było-}\mathbf{exit}} | \frac{b, s \,\longrightarrow\, \mathbf{true} \quad \quad I, s \,\longrightarrow\, s', \mbox{było-}\mathbf{exit}} | ||
{\mathbf{while}\, b \,\mathbf{do}\, I, s \,\longrightarrow\, s', \mbox{było-}\mathbf{exit}} | {\mathbf{while}\, b \,\mathbf{do}\, I, s \,\longrightarrow\, s', \mbox{było-}\mathbf{exit}} | ||
Linia 429: | Linia 434: | ||
opiszemy, jak powstaje ślad: | opiszemy, jak powstaje ślad: | ||
<math> | |||
\mathbf{exit}, s \,\Longrightarrow\, s, \mbox{było-}\mathbf{exit} | \mathbf{exit}, s \,\Longrightarrow\, s, \mbox{było-}\mathbf{exit} | ||
\quad \quad | \quad \quad | ||
Linia 439: | Linia 444: | ||
większej. Np. | większej. Np. | ||
<math> | |||
\frac{I_1, s \,\Longrightarrow\, s', \mbox{było-}\mathbf{exit}} | \frac{I_1, s \,\Longrightarrow\, s', \mbox{było-}\mathbf{exit}} | ||
{I_1;\, I_2, s \,\Longrightarrow\, s', \mbox{było-}\mathbf{exit}} | {I_1;\, I_2, s \,\Longrightarrow\, s', \mbox{było-}\mathbf{exit}} | ||
Linia 453: | Linia 458: | ||
Wreszcie zobaczmy jak zachowuje się pętla <math> \mathbf{loop}\, </math>: | Wreszcie zobaczmy jak zachowuje się pętla <math> \mathbf{loop}\, </math>: | ||
<math> | |||
\frac{I, s \,\Longrightarrow\, s', \mbox{było-}\mathbf{exit}} | \frac{I, s \,\Longrightarrow\, s', \mbox{było-}\mathbf{exit}} | ||
{\mathbf{loop}\, I, s \,\Longrightarrow\, s'} | {\mathbf{loop}\, I, s \,\Longrightarrow\, s'} | ||
Linia 466: | Linia 471: | ||
na <math> s', \mbox{było-}\mathbf{exit} </math> czy <math> s', \mbox{było-}\mathbf{continue} </math> jest | na <math> s', \mbox{było-}\mathbf{exit} </math> czy <math> s', \mbox{było-}\mathbf{continue} </math> jest | ||
''natychmiast'' widoczna w instrukcji <math> \mathbf{loop}\, I </math>, nawet jeśli | ''natychmiast'' widoczna w instrukcji <math> \mathbf{loop}\, I </math>, nawet jeśli | ||
<math> \mathbf{exit} </math> czy <math> | <math> \mathbf{exit} </math> czy <math> \mathbf{continue} </math> zostało wywołane głęboko wewnątrz | ||
<math> I </math>! | <math> I </math>! | ||
Linia 478: | Linia 483: | ||
tak, aby możliwe było jednorazowe rozwinięcie pętli <math> \mathbf{loop}\, </math>: | tak, aby możliwe było jednorazowe rozwinięcie pętli <math> \mathbf{loop}\, </math>: | ||
<math> | |||
\mathbf{loop}\, I, s \,\Longrightarrow\, I \,\mathbf{then}\, \mathbf{loop}\, I, s. | \mathbf{loop}\, I, s \,\Longrightarrow\, I \,\mathbf{then}\, \mathbf{loop}\, I, s. | ||
</math> | </math> | ||
Linia 487: | Linia 492: | ||
ale w jej ''kopii'' umieszczonej przed <math> \,\mathbf{then}\, </math>: | ale w jej ''kopii'' umieszczonej przed <math> \,\mathbf{then}\, </math>: | ||
<math> | |||
\frac{I', s \,\Longrightarrow\, s', \mbox{było-}\mathbf{exit}} | \frac{I', s \,\Longrightarrow\, s', \mbox{było-}\mathbf{exit}} | ||
{I' \,\mathbf{then}\, \mathbf{loop}\, I, s \,\Longrightarrow\, s'} | {I' \,\mathbf{then}\, \mathbf{loop}\, I, s \,\Longrightarrow\, s'} | ||
Linia 498: | Linia 503: | ||
<math> \mathbf{loop}\, </math> potrzebujemy dodatkowej reguły: | <math> \mathbf{loop}\, </math> potrzebujemy dodatkowej reguły: | ||
<math> | |||
\frac{I', s \,\Longrightarrow\, I'', s'} | \frac{I', s \,\Longrightarrow\, I'', s'} | ||
{I' \,\mathbf{then}\, \mathbf{loop}\, I, s \,\Longrightarrow\, I'' \,\mathbf{then}\, \mathbf{loop}\, I, s'} | {I' \,\mathbf{then}\, \mathbf{loop}\, I, s \,\Longrightarrow\, I'' \,\mathbf{then}\, \mathbf{loop}\, I, s'} | ||
Linia 512: | Linia 517: | ||
Zatem ostatecznie nasze reguły mogą wyglądać tak: | Zatem ostatecznie nasze reguły mogą wyglądać tak: | ||
<math> | |||
\mathbf{exit}, s \,\Longrightarrow\, \mbox{było-}\mathbf{exit} | \mathbf{exit}, s \,\Longrightarrow\, \mbox{było-}\mathbf{exit} | ||
\quad \quad | \quad \quad | ||
Linia 518: | Linia 523: | ||
</math> | </math> | ||
<math> | |||
\frac{I_1, s \,\Longrightarrow\, \mbox{było-}\mathbf{exit}} | \frac{I_1, s \,\Longrightarrow\, \mbox{było-}\mathbf{exit}} | ||
{I_1;\, I_2, s \,\Longrightarrow\, \mbox{było-}\mathbf{exit}} | {I_1;\, I_2, s \,\Longrightarrow\, \mbox{było-}\mathbf{exit}} | ||
Linia 526: | Linia 531: | ||
</math> | </math> | ||
<math> | |||
\mathbf{loop}\, I, s \,\Longrightarrow\, I \,\mathbf{then}\, \mathbf{loop}\, I, s. | \mathbf{loop}\, I, s \,\Longrightarrow\, I \,\mathbf{then}\, \mathbf{loop}\, I, s. | ||
</math> | </math> | ||
<math> | |||
\frac{I', s \,\Longrightarrow\, \mbox{było-}\mathbf{exit}} | \frac{I', s \,\Longrightarrow\, \mbox{było-}\mathbf{exit}} | ||
{I' \,\mathbf{then}\, \mathbf{loop}\, I, s \,\Longrightarrow\, s} | {I' \,\mathbf{then}\, \mathbf{loop}\, I, s \,\Longrightarrow\, s} | ||
Linia 538: | Linia 543: | ||
</math> | </math> | ||
<math> | |||
\frac{I', s \,\Longrightarrow\, I'', s'} | \frac{I', s \,\Longrightarrow\, I'', s'} | ||
{I' \,\mathbf{then}\, \mathbf{loop}\, I, s \,\Longrightarrow\, I'' \,\mathbf{then}\, \mathbf{loop}\, I, s'} | {I' \,\mathbf{then}\, \mathbf{loop}\, I, s \,\Longrightarrow\, I'' \,\mathbf{then}\, \mathbf{loop}\, I, s'} |
Wersja z 08:27, 7 sie 2006
Zawartość
Kończymy semantykę małych kroków i rozpoczynamy semantykę naturalną (duże kroki). Uzupełnimy semantykę naturalną języka Tiny o semantykę naturalną dla wyrażeń boolowskich i arytmetycznych i semantykę dla błędów wykonania. Wreszcie dodamy instrukcję pętli i instrukcje niestrukturalnego zakończenia pętli (instrukcje i ).
Rozszerzenia semantyki języka Tiny
Zadanie 1
Zdefiniuj znaczenie wyrażeń boolowskich i arytmetycznych w języku Tiny, w stylu dużych kroków (semantyka naturalna).
Rozwiązanie
Zadanie 2
Rozważ dodatkowo operację dzielenia:
i rozszerz semantykę z poprzedniego zadania. Dzielenie przez zero jest błądem i kończy natychmiast wykonanie programu. Oprócz stanu wynikiem programu powinna byc informacja o błędzie, jeśli błąd wystąpił.
Rozwiązanie (szkic)
Dopóki nie wystąpi błąd dzielenia przez zero, semantyka programu powinna być identyczna jak w poprzednim zadaniu. Zatem pozostawiamy wszystkie reguły z poprzedniego zadania. Dodatkowo potrzebujemy reguł, które opiszą
- kiedy powstaje błąd oraz
- jak zachowuje się program po wystąpieniu błędu
Zaczynamy od pierwszego punktu. W tym celu dodajemy do konfiguracji jedną konfigurację końcową . Reguła opisująca powstanie błędu może wyglądać np. tak:
Pomijamy tutaj reguły dla przypadku, gdy oblicza się do wartości różnej od zera. Ponadto dla czytelności przyjęliśmy, że wynikiem tranzycji jest wyłącznie informacja o błędzie, a stan jest zapominany. Bez trudu możnaby wszystkie reguły (zarówno te powyżej jak i te poniżej) zmodyfikować tak, by wraz z informacją o błędzie zwracany był też stan, w którym błąd się pojawił. Np. ostatnia reguła wyglądałaby następująco:
i zamiast pojedyńczej konfiguracji końcowej potrzebowalibyśmy oczywiście całego zbioru .
Przejdźmy teraz do drugiego punktu. Potrzebujemy dodatkowych reguł, które zagwarantują, że błąd, raz pojawiwszy się, propaguje się przez wszystkie konstrukcje składniowe, a normalne obliczenie wyrażenia jest wstrzymame.
Następnie, błąd w wyrażeniu powinien wstrzymać normalne wykonanie instrukcji:
I wreszcie błąd powinien propagować się do kolejnych instrukcji:
Zadanie 3
Rozszerz język Tiny o następującą instrukcję pętli:
to instrukcja pętli, stanowi instrukcję wewnętrzną. Instrukcja wychodzi z nabliższej pętli i kontynuuje wykonanie programu od pierwszej instrukcji za tą pętlą. Instrukcje powraca na początek instrukcji wewnętrznej najbliższej pętli.
Pozważ zarówno semantykę naturalną jak i semantykę małych kroków.
Rozwiązanie 1 (semantyka naturalna)
Dodamy do reguł semantyki naturalnej dla języka Tiny kilka nowych reguł opisujących nową konstrukcję języka i jej interakcję z pozostałymi konstrukcjami.
Pomysł polega na dodaniu specjalnych konfiguracji zawierających informację o tym, że została wykonana instrukcja lub . Oto odpowiednie reguły:
Czyli instrukcje i nie modyfikują stanu , ale zostawiają po sobie \ślad". Zauważmy, że taki ślad zostaje pozostawiony tylko wtedy, jesli nie było dotychczas innego śladu, to znaczy jeśli (lub ) zostało wykonane w zwykłym stanie . Oczywiście poszerzamy odpowiednio zbiór konfiguracji o:
</math>[ \mathbf{State} \times \{ \mbox{było-}\mathbf{exit}, \mbox{było-}\mathbf{continue} \} </math> , Pytanie: jakie powinno być zachowanie i w konfiguracji lub ? Czy instrukcje i będą faktycznie wykonywane w takich konfiguracjach?
Zapiszmy teraz jak inne instrukcje korzystają z dodatkowej informacji (śladu) zawartej w konfiguracjach. Oczywiście beneficjentem tej informacji jest instrukcji :
Czyli w zależności od tego, jaki ślad został zarejestrowany podczas wykonania , albo kończymy wykonanie pętli , albo rozpoczynamy kolejną iterację. Zauważmy, że stan może być różny od , ponieważ zanim wykonała się ktoraś z instrukcji lub , mogły zostać zmienione wartości niektórych zmiennych.
Oczywiście, jeśli instrukcja wewnętrzna zakończyła się normalnie, kontynuujemy wykonanie pętli podobnie jak w przypadku wywołania :
Pytanie: czy potrzebujemy dodatkowo reguł postaci:
Okazuje się że nie, ponieważ ślad powinien zostać zawsze wymazany przez pętlę . Poza tym reguły te wykraczałyby poza klasyczna podejście semantyki naturalnej, w którym zwykle bezpośrednio definiujemy tranzycje postaci .
Teraz musimy określić zachowanie wszystkich instrukcji w sytuacji, gdy bieżąca konfiguracja zawiera już ślad. Zasadniczo, powinniśmy zaniechać wykonania instrukcji (w przypadku pętli, powinniśmy zaniechać dalszego iterowania tej pętli). Oto odpowiednie reguły dla :
Pominęliśmy zupełnie analogiczne reguły dla konfiguracji . Zwróćmy szczególnie uwagę na ostatnią regułę dla pętli : wyraża ona przypadek, gdy ślad został wygenerowany nie w pierwszym obiegu pętli, ale w którymś z kolejnych. Musieliśmy rozważyc również ten przypadek, ponieważ wybraliśmy podejście dużych kroków; w podejściu małych kroków nie byłoby to zapewne konieczne. Zauważmy też, że dla pętli nie rozpatrujemy przypadku, gdy dozór oblicza się do , gdyż w tym przypadku nie ma możliwości wygenerowania śladu.
Zauważmy, że nasze reguły nie pozwalają na dodanie drugiego (kolejnego) śladu!
Rozwiązanie 2 (małe kroki)
W semantyce naturalnej musieliśmy napisać wiele reguł aby zapewnić pomijanie instrukcji w sytuacji, gdy został juz zarejestrowany jakiś ślad. Było to dość uciążliwe. Okazuje się, że podejście mało-krokowe oferuje możliwość bardziej eleganckiego rozwiązania.
Punktem startowym sę teraz reguły mało-krokowe dla języka Tiny.
Podobnie jak poprzednio rozszerzymy zbiór konfiguracji i podobnie opiszemy, jak powstaje ślad:
Ponadto musimy określić sposób, w jaki mały krok mniejszej instrukcji zostaje zamieniony na mały krok większej. Np.
Zauważmy, że nie musimy zajmowac się przypadkiem, gdy ślad powstaje w , bo wybraliśmy podejście mało-krokowe. Ponadto, nie musimy opisywać instrukcji warunkowej i pętli , ponieważ ślad nie może powstać podczas oblcizania dozoru!
Wreszcie zobaczmy jak zachowuje się pętla :
Reguły te są prawie identyczne do reguł semantyki naturalnej dla tej sytuacji! Natomiast korzystamy z tego, że w podejściu mało-krokowym zmiana konfiguracji na czy jest natychmiast widoczna w instrukcji , nawet jeśli czy zostało wywołane głęboko wewnątrz !
Niestety, powyzsze reguły nie są poprawne! Dlaczego? Jak zwykle w semantyce małych kroków, wykonując instrukcję wewnętrzną zapominamy stopniowo jaka była ona na początku. I w związku z tym nie potrafimy poprawnie powrócić do wykonywania pętli po wywołaniu .
Prostym sposobem poprawienia naszego blędu jest rozszerzenie składni tak, aby możliwe było jednorazowe rozwinięcie pętli :
Teraz możemy zapisać dwie powyższe reguły dla w poprawnej wersji, pamiętając o tym, że i pojawią się nie w instrukcji wewnętrznej, ale w jej kopii umieszczonej przed :
A ponieważ wewnątrz kopii mogą być zagnieżdzone instrukcje potrzebujemy dodatkowej reguły:
Na koniec zauważmy, że stan w pierwszych dwóch z powyższych trzech reguł nigdy nie jest różny od . Zatem równoważnie moglibyśmy zamienić na w powyższych dwóch regułach. Ale wtedy okazuje się , w parze z albo jest nadmiarowe i może zostać wyeliminowane.
Zatem ostatecznie nasze reguły mogą wyglądać tak:
a zbiór konfiguracji poszerzamy tylko o
Zadania domowe
Zadanie 1
Zaproponuj semantykę mało-krokową języka z zdania 2. Czy różni się ona istotnie od semantyki naturalnej?
Zadanie 2
Napisz semantyję naturalną dla nieznacznie rozszerzonej wersji instrukcji :
Identyfikator pełni tutaj rolę etykiety przypisanej instrukcji , jest też parametrem dwóch pozostałych instrukcji. kończy teraz najbliższą otaczającą pętlę o etykiecie . Podobnie wznawia najbliższą pętlę o etykiecie . Np. program
Parser nie mógł rozpoznać (błąd składni): {\displaystyle x: \mathbf{loop}\,\\ \quad \quad a := 1; \quad \quad y: \mathbf{loop}\, \quad \quad \quad \quad \mathbf{exit} x; \quad \quad \quad \quad a := a-10; \quad \quad a := a+1; a := a+2; }
kończy działanie z wartością zmiennej . Zauważmy, że musieliśmy jakoś określić, do wnętrza której pętli należą trzy ostatnie instrukcje. Użyliśmy to tego celu wcięć a niejednoznaczność bierze się oczywiście stąd, że pracujemy ze składnią abstrakcyjną. Składnia konkretna zawierałaby prawdopodobnie jakąś konstukcję zamykającą pętlę , np. .
Zadanie 3
Napisz semantykę naturalną i mało-krokową dla rozszerzenia języka Tiny o wyrażenia z efektami ubocznymi:
Obliczenie wyrażenia polega na wykonaniu a potem na obliczeniu . Wartość wyrażenia jest taka jak wartość wyrażenia a efektem ubocznym jest podstawienie tej wartości na zmienną .