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

Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania
Sl (dyskusja | edycje)
Nie podano opisu zmian
m Zastępowanie tekstu – „,↵</math>” na „</math>,”
 
(Nie pokazano 12 wersji utworzonych przez 3 użytkowników)
Linia 1: Linia 1:


== Zawartość ==
== Zawartość ==


Kończymy semantykę małych kroków i rozpoczynamy semantykę naturalną (duże kroki).
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
Uzupełnimy semantykę naturalną języka TINY o semantykę naturalną wyrażeń boolowskich i arytmetycznych oraz semantykę błędów wykonania.
wyrażeń boolowskich i arytmetycznych i semantykę dla
Wreszcie dodamy nową instrukcję pętli <math>\mathbf{loop}\ </math>,, pozwalającą na niestrukturalne przerwanie lub wznowienie iteracji (instrukcje <math>\mathbf{exit}</math> i <math>\mathbf{continue}</math>).
błędów wykonania.
Wreszcie dodamy instrukcję pętli <math> \mathbf{loop}\, </math> i instrukcje
niestrukturalnego zakończenia pętli (instrukcje <math> \mathbf{exit}</math> i <math> \mathbf{continue} </math>).




Linia 14: Linia 10:




==== Zadanie 1 ====
{{cwiczenie|1|cw1|


Zdefiniuj znaczenie wyrażeń boolowskich i arytmetycznych
Zdefiniuj znaczenie wyrażeń boolowskich i arytmetycznych w języku TINY w stylu dużych kroków (semantyka naturalna).
w języku Tiny, w stylu dużych kroków (semantyka naturalna).
}}


==== Rozwiązanie ====




<div class="mw-collapsible mw-made=collapsible mw-collapsed">
<span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie</span>
<div class="mw-collapsible-content" style="display:none">


Przypomnijmy składnię wyrażeń boolowskich i arytmetycznych
Przypomnijmy składnię wyrażeń boolowskich i arytmetycznych języka TINY:
jezyka Tiny:


<math>
<math>
Linia 37: Linia 34:
l \, ::= \,\,
l \, ::= \,\,
         \mathbf{true}    \,\,|\,\,
         \mathbf{true}    \,\,|\,\,
         \mathbf{true}         
         \mathbf{false}         
</math>
</math>


Linia 55: Linia 52:
</math>
</math>


Chcemy, aby tranzycje wyrażen wyglądały następująco:
Chcemy, aby tranzycje wyrażeń wyglądały następująco:


<math>
<math>
e, s \longrightarrow n   
e, s \longrightarrow n   
\quad \quad \quad
\quad \quad \quad
b, s \longrightarrow l,
b, s \longrightarrow l</math>,
</math>


gdzie <math> s \in \mathbf{State} </math>, <math> n \in </math> jest liczbą całkowitą,  
gdzie <math>s \in \mathbf{State}</math>, <math>n \in</math> jest liczbą całkowitą, <math>n \in \mathbf{Num}</math>, a <math>l \in \mathbf{Bool} = \{ \mathbf{true}, \mathbf{false} \}</math>.
<math> n \in \mathbf{Num} </math>, a <math> l \in \mathbf{Bool} = \{ \mathbf{true}, \mathbf{true} \} </math>.
Tranzycja taka oznacza, że wyrażenie <math>e</math> w stanie <math>s</math> wylicza się do wartości <math>n</math> oraz analogicznie, wyrażenie logiczne <math>b</math> w stanie <math>s</math> wylicza się do <math>l</math>.
Tranzycja taka oznacza, że wyrażenie <math> e </math> w stanie <math> s </math> wylicza się do
wartości <math> n </math> oraz analogicznie, wyrażenie logiczne <math> b </math> w
stanie <math> s </math> wylicza się do <math> l </math>.
Zatem zbiór konfiguracji dla semantyki całego języka Tiny to znów
Zatem zbiór konfiguracji dla semantyki całego języka Tiny to znów


Linia 74: Linia 67:
\mathbf{Num} \, \cup \, \mathbf{Bool} \, \cup \, \mathbf{State}
\mathbf{Num} \, \cup \, \mathbf{Bool} \, \cup \, \mathbf{State}
</math>
</math>
a konfiguracje końcowe to <math> \mathbf{State} </math> tak jak poprzednio.
a konfiguracje końcowe to <math>\mathbf{State}</math> tak jak poprzednio.
Tranzycje dla instrukcji pozostają zasadniczo bez zmian, z tym,
Tranzycje dla instrukcji pozostają zasadniczo bez zmian, z tym że odwołania do funkcji semantycznych dla wyrażen zastępujemy przez odpowiednie tranzycje.
że odwołania do funkcji semantycznych dla wyrażen zastępujemy
przez odpowiednie tranzycje.
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:


Linia 86: Linia 77:


<math>
<math>
\frac{b, s \,\longrightarrow\, \mathbf{true}}
\frac{b, s \,\longrightarrow\, \mathbf{false}}
     {\mathbf{while}\, b \,\mathbf{do}\, I, s \,\longrightarrow\, s}
     {\mathbf{while}\, b \,\mathbf{do}\, I, s \,\longrightarrow\, s}
</math>
</math>
Linia 92: Linia 83:
Podobnie dla instrukcji warunkowej.
Podobnie dla instrukcji warunkowej.
Teraz zajmiemy się tranzycjami dla wyrażeń.
Teraz zajmiemy się tranzycjami dla wyrażeń.
Zacznijmy od stalych arytmetycznych i boolowskich:
Zacznijmy od stałych arytmetycznych i boolowskich:


<math>
<math>
n, s \,\longrightarrow\, n
n, s \,\longrightarrow\, n
\quad \quad
\quad \quad
l, s \,\longrightarrow\, l.
l, s \,\longrightarrow\, l</math>
</math>


Operatory arytmetyczne definiujemy następująco:
Operatory arytmetyczne definiujemy następująco:
Linia 109: Linia 99:
</math>
</math>


Czyli aby obliczyć sumę <math> e_1 + e_2 </math> w stanie  
Czyli aby obliczyć sumę <math>e_1 + e_2</math> w stanie <math>s</math>, trzeba najpierw obliczyć <math>e_1</math> i <math>e_2</math> w tym stanie, a następnie dodać obliczone wartości.
<math> s </math>, trzeba najpierw obliczyć <math> e_1 </math> i  
Zauważmy, że nie specyfikujemy kolejności, w jakiej mają się obliczać obydwa podwyrażenia.
<math> e_2 </math> w tym stanie, a następnie dodać obliczone wartości.
I choć tutaj nie ma to żadnego znaczenia, w przyszłości będzie inaczej, gdy jezyk będzie umożliwiał efekty uboczne podczas obliczania wyrażeń.
Zauważmy, że nie specyfikujemy kolejności, w jakiej mają się
obliczać obydwa podwyrażenia.
I choć tutaj nie ma to żadnego znaczenia, w przyszłości  
będzie inaczej, gdy jezyk będzie umożliwiał efekty uboczne  
podczas obliczania wyrażeń.


Podobne reguły można napisać dla pozostałych operacji
Podobne reguły można napisać dla pozostałych operacji arytmetycznych, oraz dla spójników logicznych:
arytmnetycznych, oraz dla spójników logicznych:


<math>
<math>
Linia 128: Linia 112:
</math>
</math>


Oto inny wariant, reguły lewo-stronne (ponieważ rozpoczynamy od ''lewego'' koniunktu):
(strategia gorliwa).
Reguły dla <math>\leq</math> są następujące:


<math>
<math>
\frac{b_1, s \,\longrightarrow\, \mathbf{true}}
\frac{e_1, s \,\longrightarrow\, n_1 \quad \quad e_2, s \,\longrightarrow\, n_2 \quad \quad n_1 \leq n_2}
     {b_1 \land b_2, s \,\longrightarrow\, \mathbf{true}}
    {e_1 \leq e_2, s \,\longrightarrow\, \mathbf{true}}
\quad \quad
\frac{e_1, s \,\longrightarrow\, n_1 \quad \quad e_2, s \,\longrightarrow\, n_2 \quad \quad n_1 > n_2}
     {e_1 \leq e_2, s \,\longrightarrow\, \mathbf{false}}
</math>
 
Oto inny wariant semantyki spójnika <math>\land</math>, tzw. strategia lewostronna (ponieważ rozpoczynamy od ''lewego'' koniunktu):


<math>
\frac{b_1, s \,\longrightarrow\, \mathbf{false}}
    {b_1 \land b_2, s \,\longrightarrow\, \mathbf{false}}
\quad \quad
\frac{b_1, s \,\longrightarrow\, \mathbf{true}  \quad \quad   
\frac{b_1, s \,\longrightarrow\, \mathbf{true}  \quad \quad   
       b_2, s \,\longrightarrow\, l}
       b_2, s \,\longrightarrow\, l}
Linia 139: Linia 134:
</math>
</math>


Inny wariant to wariant prawo-stronny (
Inny wariant to strategia prawostronna (najpierw <math>b_2</math>, potem <math>b_1</math>).
najpierw <math> b_2 </math>, potem <math> b_1 </math>).
Wreszcie rozważmy kombinację obydwu semantyk (strategia ''równoległa'' lub ''leniwa''):
Wreszcie rozważmy kombinację obydwu semantyk (reguły ''równoległe''):


<math>
<math>
\frac{b_1, s \,\longrightarrow\, \mathbf{true}}
\frac{b_1, s \,\longrightarrow\, \mathbf{false}}
     {b_1 \land b_2, s \,\longrightarrow\, \mathbf{true}}
     {b_1 \land b_2, s \,\longrightarrow\, \mathbf{false}}
\quad \quad \quad
\quad \quad \quad
\frac{b_2, s \,\longrightarrow\, \mathbf{true}}
\frac{b_2, s \,\longrightarrow\, \mathbf{false}}
       {b_1 \land b_2, s \,\longrightarrow\, \mathbf{true}}
       {b_1 \land b_2, s \,\longrightarrow\, \mathbf{false}}
</math>
</math>


Czyli jeśli którekolwiek z podwyrażeń daje wynik <math> \mathbf{true} </math>,
Czyli jeśli którekolwiek z podwyrażeń daje wynik <math>\mathbf{false}</math>, to taki wynik zyskuje całe wyrażenie.
to taki wynik zyskuje całe wyrażenie.
Dodatkowo potrzebujemy jeszcze reguły:
Dodatkowo potrzebujemy jeszcze reguły:


Linia 161: Linia 154:
</math>
</math>


W naszym prostym języku wszystkie cztery warianty
'''Pytanie:''' czy w naszym prostym języku wszystkie cztery strategie obliczania spójnika <math>\land</math> są równoważne?
są równoważne.
 
Reguły dla pozostałych spójników logicznych, dla
Reguły dla negacji oraz dla instrukcji przypisania pozostawiamy jako proste ćwiczenie.
negacji oraz dla instrukcji przypisania pozostawiamy jako proste
ćwiczenie.


</div></div>






==== Zadanie 2 ====
{{cwiczenie|2|cw2|


Rozważ dodatkowo operację dzielenia:
Rozważ dodatkowo operację dzielenia:
Linia 180: Linia 172:


i rozszerz semantykę z poprzedniego zadania.
i rozszerz semantykę z poprzedniego zadania.
Dzielenie przez zero jest błądem i kończy natychmiast wykonanie
Dzielenie przez zero jest błędem i kończy natychmiast wykonanie programu.
programu.
Oprócz stanu wynikiem programu powinna byc informacja o błędzie, jeśli błąd wystąpił.
Oprócz stanu wynikiem programu powinna byc informacja o błędzie,
}}
jeśli błąd wystąpił.
 
==== Rozwiązanie (szkic) ====




<div class="mw-collapsible mw-made=collapsible mw-collapsed">
<span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie</span>
<div class="mw-collapsible-content" style="display:none">


Dopóki nie wystąpi błąd dzielenia przez zero, semantyka programu
Dopóki nie wystąpi błąd dzielenia przez zero, semantyka programu
powinna być identyczna jak w poprzednim zadaniu. Zatem pozostawiamy
powinna być identyczna jak w poprzednim zadaniu. Zatem pozostawiamy wszystkie reguły z poprzedniego zadania.
wszystkie reguły z poprzedniego zadania.
Dodatkowo potrzebujemy reguł, które opiszą
Dodatkowo potrzebujemy reguł, które opiszą


Linia 198: Linia 189:


Zaczynamy od pierwszego punktu.
Zaczynamy od pierwszego punktu.
W tym celu dodajemy do konfiguracji jedną konfigurację końcową
W tym celu dodajemy do konfiguracji jedną konfigurację końcową <math>\mathtt{Blad}</math>.
<math> \mathtt{Blad} </math>.
Reguła opisująca powstanie błędu może wyglądać np. tak (duże i małe kroki):
Reguła opisująca powstanie błędu może wyglądać np. tak:


<math>
<math>
\frac{e_2, s \longrightarrow 0}
\frac{e_2, s \,\longrightarrow\, 0}
{e_1 / e_2, s \longrightarrow Blad}
{e_1 / e_2, s \,\longrightarrow\, \mathtt{Blad}}
</math>
\quad \quad
e_1 / 0, s \,\Longrightarrow, \mathtt{Blad}</math>


Pomijamy tutaj reguły dla przypadku, gdy <math>e_2</math>
Pomijamy tutaj reguły dla przypadku, gdy <math>e_2</math> oblicza się do wartości różnej od zera.
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.
Ponadto dla czytelności przyjęliśmy, że wynikiem tranzycji jest
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ł.  
wyłącznie informacja o błędzie, a stan jest zapominany.
Np. ostatnia reguła wyglądałaby następująco:
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:


<math>
<math>
e_1 / 0, s \Longrightarrow Blad, s
\frac{e_2, s \,\longrightarrow\, 0}
{e_1 / e_2, s \,\longrightarrow\, \mathtt{Blad}, s}
\quad \quad
e_1 / 0, s \,\Longrightarrow, \mathtt{Blad}, s
</math>
</math>


i zamiast pojedyńczej konfiguracji końcowej <math> \mathtt{Blad} </math> potrzebowalibyśmy
i zamiast pojedyńczej konfiguracji końcowej <math>\mathtt{Blad}</math> potrzebowalibyśmy oczywiście całego zbioru <math>\{ \mathtt{Blad} \} \times \mathbf{State}</math>.
oczywiście całego zbioru <math> \{ \mathtt{Blad} \} \times \mathbf{State} </math>.


Przejdźmy teraz do drugiego punktu. Potrzebujemy dodatkowych reguł,
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.
które zagwarantują, że błąd, raz pojawiwszy się, propaguje się przez
wszystkie konstrukcje składniowe, a normalne obliczenie wyrażenia
jest wstrzymame.


<math>
<math>
Linia 264: Linia 250:
     {\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}}
\quad \quad \quad
\quad \quad \quad
\frac{b, s \,\longrightarrow\, \mathbf{true} \quad \quad I_2, s \,\longrightarrow\, \mathtt{Blad}}
\frac{b, s \,\longrightarrow\, \mathbf{false} \quad \quad I_2, 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}}
</math>
</math>
Linia 277: Linia 263:
</math>
</math>


Zwróćmy szczególnie uwagę na ostatnią regułę dla pętli <math>\mathbf{while}\ </math>,: wyraża ona przypadek, gdy błąd 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.
</div></div>






==== Zadanie 3 ====
{{cwiczenie|3|cw3|


Rozszerz język Tiny o następującą instrukcję pętli:
Rozszerzmy język TINY o następującą instrukcję pętli:


<math>
<math>
Linia 291: Linia 281:
</math>
</math>


<math> \mathbf{loop}\, I </math> to instrukcja pętli, <math> I </math> stanowi instrukcję wewnętrzną.
<math>\mathbf{loop}\, I</math> to instrukcja pętli, <math>I</math> stanowi instrukcję wewnętrzną.
Instrukcja <math> \mathbf{exit} </math> wychodzi z nabliższej pętli <math> \mathbf{loop}\, </math>
Instrukcja <math>\mathbf{exit}</math> wychodzi z nabliższej otaczającej pętli <math>\mathbf{loop}\ </math>, i kontynuuje wykonanie programu od pierwszej instrukcji za tą pętlą.
i kontynuuje wykonanie programu od pierwszej instrukcji za tą pętlą.
Instrukcja <math>\mathbf{continue}</math> powraca na początek instrukcji wewnętrznej najbliższej otaczającej pętli <math>\mathbf{loop}\ </math>,.
Instrukcje <math> \mathbf{continue} </math> powraca na początek instrukcji wewnętrznej
najbliższej pętli.


Pozważ zarówno semantykę naturalną jak i semantykę małych kroków.
Pozważ zarówno semantykę naturalną, jak i semantykę małych kroków.
}}




==== Rozwiązanie 1 (semantyka naturalna) ====




<div class="mw-collapsible mw-made=collapsible mw-collapsed">
<span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie</span>
<div class="mw-collapsible-content" style="display:none">


Dodamy do reguł semantyki naturalnej dla języka Tiny
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.
kilka nowych reguł opisujących nową konstrukcję języka
i jej ''interakcję'' z pozostałymi konstrukcjami.


Pomysł polega na dodaniu specjalnych konfiguracji zawierających
Pomysł polega na dodaniu specjalnych konfiguracji zawierających informację o tym, że została wykonana instrukcja <math>\mathbf{exit}</math> lub <math>\mathbf{continue}</math>. Oto odpowiednie reguły:
informację o tym, że została wykonana instrukcja <math> \mathbf{exit} </math>
lub <math> \mathbf{continue} </math>. Oto odpowiednie reguły:


<math>
<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
\mathbf{continue}, s \,\longrightarrow\, s, \mbox{było-}\mathbf{continue}.
\mathbf{continue}, s \,\longrightarrow\, s, \mbox{było-}\mathbf{continue}</math>
</math>


Czyli instrukcje <math> \mathbf{exit} </math> i <math> \mathbf{continue} </math> nie modyfikują
Czyli instrukcje <math>\mathbf{exit}</math> i <math>\mathbf{continue}</math> nie modyfikują stanu <math>s</math>, ale zostawiają po sobie "ślad".  
stanu <math> s </math>, ale zostawiają po sobie \''ślad".  
Zauważmy, że taki ślad zostaje pozostawiony tylko wtedy, jeśli nie było dotychczas innego śladu, to znaczy jeśli <math>\mathbf{exit}</math> (lub <math>\mathbf{continue}</math>) zostało wykonane w zwykłym stanie <math>s</math>.
Zauważmy, że taki ślad zostaje pozostawiony tylko wtedy, jesli
nie było dotychczas innego śladu, to znaczy jeśli <math> \mathbf{exit} </math>
(lub <math> \mathbf{continue} </math>) zostało wykonane w zwykłym stanie <math> s </math>.
Oczywiście poszerzamy odpowiednio zbiór konfiguracji o:
Oczywiście poszerzamy odpowiednio zbiór konfiguracji o:


</math>[
<math>
\mathbf{State} \times \{ \mbox{było-}\mathbf{exit}, \mbox{było-}\mathbf{continue} \}
\mathbf{State} \times \{ \mbox{było-}\mathbf{exit}, \mbox{było-}\mathbf{continue} \}</math>
</math>
 
,
'''Pytanie''': jakie powinno być zachowanie <math>\mathbf{exit}</math> i <math>\mathbf{continue}</math> w konfiguracji <math>s, \mbox{było-}\mathbf{exit}</math> lub <math>s, \mbox{było-}\mathbf{continue}</math>?
'''Pytanie''': jakie powinno być zachowanie <math> \mathbf{exit} </math> i
Czy instrukcje <math>\mathbf{exit}</math> i <math>\mathbf{continue}</math> będą faktycznie wykonywane w takich konfiguracjach?
<math> \mathbf{continue} </math> w konfiguracji <math> s, \mbox{było-}\mathbf{exit} </math>
lub <math> s, \mbox{było-}\mathbf{continue} </math>?
Czy instrukcje <math> \mathbf{exit} </math> i <math> \mathbf{continue} </math>
będą faktycznie wykonywane w takich konfiguracjach?


Zapiszmy teraz jak inne instrukcje korzystają z dodatkowej informacji
Zapiszmy teraz, jak inne instrukcje korzystają z dodatkowej informacji (śladu) zawartej w konfiguracjach.
(śladu) zawartej w konfiguracjach.
Oczywiście "beneficjentem" korzystającym z tej informacji jest instrukcja <math>\mathbf{loop}\ </math>,:
Oczywiście beneficjentem tej informacji jest instrukcji <math> \mathbf{loop}\, </math>:


<math>
<math>
Linia 347: Linia 325:
</math>
</math>


Czyli w zależności od tego, jaki ślad został zarejestrowany
Czyli w zależności od tego, jaki ślad został zarejestrowany podczas wykonania <math>I</math>, albo kończymy wykonanie  pętli <math>\mathbf{loop}\ </math>,, albo rozpoczynamy kolejną iterację.
podczas wykonania <math> I </math>, albo kończymy wykonanie  pętli <math> \mathbf{loop}\, </math>,
Zauważmy, że stan <math>s'</math> może być różny od <math>s</math>, ponieważ zanim wykonała się ktoraś z instrukcji <math>\mathbf{exit}</math> lub
albo rozpoczynamy kolejną iterację.
<math>\mathbf{continue}</math> mogły zostać zmienione wartości niektórych zmiennych.
Zauważmy, że stan <math> s' </math> może być różny od <math> s </math>, ponieważ
zanim wykonała się ktoraś z instrukcji <math> \mathbf{exit} </math> lub
<math> \mathbf{continue} </math>, mogły zostać zmienione wartości niektórych zmiennych.


Oczywiście, jeśli instrukcja wewnętrzna <math> I </math> zakończyła się
Oczywiście, jeśli instrukcja wewnętrzna <math>I</math> zakończyła się "normalnie", kontynuujemy wykonanie pętli podobnie jak w przypadku wywołania <math>\mathbf{continue}</math>:
''normalnie'', kontynuujemy wykonanie pętli podobnie jak w przypadku  
wywołania <math> \mathbf{continue} </math>:


<math>
<math>
Linia 373: Linia 346:
</math>
</math>


Okazuje się że nie, ponieważ ślad powinien zostać zawsze
Okazuje się że nie, ponieważ ślad powinien zostać zawsze "wymazany" przez pętlę <math>\mathbf{loop}\ </math>,.
''wymazany'' przez pętlę <math> \mathbf{loop}\, </math>.
Poza tym reguły te wykraczałyby poza klasyczna podejście semantyki
naturalnej, w którym zwykle bezpośrednio definiujemy
tranzycje postaci <math> I, s \,\longrightarrow\, s' </math>.


Teraz musimy określić zachowanie wszystkich instrukcji w sytuacji,
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).
gdy bieżąca konfiguracja zawiera już ślad. Zasadniczo, powinniśmy
Oto odpowiednie reguły dla <math>\mbox{było-}\mathbf{exit}</math>:
zaniechać wykonania instrukcji (w przypadku pętli, powinniśmy
zaniechać dalszego iterowania tej pętli).
Oto odpowiednie reguły dla <math> \mbox{było-}\mathbf{exit} </math>:


<math>
<math>
Linia 397: Linia 363:
     {\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}}
\quad \quad
\quad \quad
\frac{b, s \,\longrightarrow\, \mathbf{true} \quad \quad I_2, s \,\longrightarrow\, s', \mbox{było-}\mathbf{exit}}
\frac{b, s \,\longrightarrow\, \mathbf{false} \quad \quad 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}}
     {\mathbf{if}\, b \,\mathbf{then}\, I_1 \,\mathbf{else}\, I_2, s \,\longrightarrow\, s', \mbox{było-}\mathbf{exit}}
</math>
</math>
Linia 410: Linia 376:
</math>
</math>


Pominęliśmy zupełnie analogiczne reguły dla konfiguracji
Pominęliśmy zupełnie analogiczne reguły dla <math>\mbox{było-}\mathbf{continue}</math>.
<math> s', \mbox{było-}\mathbf{continue} </math>.
Zauważmy, że dla pętli <math>\mathbf{while}\ </math>, nie rozpatrujemy przypadku, gdy dozór <math>b</math> oblicza się do <math>\mathbf{false}</math>, gdyż w tym przypadku nie ma możliwości wygenerowania śladu.
Zwróćmy szczególnie uwagę na ostatnią regułę dla pętli <math> \mathbf{while}\, </math>:
wyraża ona przypadek, gdy ślad <math> \mathbf{exit} </math> 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 <math> \mathbf{while}\, </math> nie rozpatrujemy przypadku,
gdy dozór <math> b </math> oblicza się do <math> \mathbf{true} </math>, gdyż w tym przypadku
nie ma możliwości wygenerowania śladu.
 
Zauważmy, że nasze reguły nie pozwalają na dodanie drugiego (kolejnego) śladu!
 
 


Zauważmy też, że nasze reguły nie pozwalają na dodanie drugiego (kolejnego) śladu!


</div></div>


==== Rozwiązanie 2 (małe kroki) ====




<div class="mw-collapsible mw-made=collapsible mw-collapsed">
<span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie</span>
<div class="mw-collapsible-content" style="display:none">


W semantyce naturalnej musieliśmy napisać wiele reguł aby  
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.
zapewnić pomijanie instrukcji w sytuacji, gdy został juz
Okazuje się, że podejście mało-krokowe oferuje możliwość bardziej eleganckiego rozwiązania.
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.
Punktem startowym sę teraz reguły mało-krokowe dla języka TINY.


Podobnie jak poprzednio rozszerzymy zbiór konfiguracji i podobnie
Podobnie jak poprzednio, rozszerzymy zbiór konfiguracji i podobnie opiszemy, jak powstaje ślad:
opiszemy, jak powstaje ślad:


<math>
<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
\mathbf{continue}, s \,\Longrightarrow\, s, \mbox{było-}\mathbf{continue}.
\mathbf{continue}, s \,\Longrightarrow, s, \mbox{było-}\mathbf{continue}</math>
</math>


Ponadto musimy określić sposób, w jaki mały krok  
Ponadto musimy określić sposób, w jaki mały krok mniejszej instrukcji zostaje zamieniony na mały krok większej. Np.
mniejszej instrukcji zostaje zamieniony na mały krok
większej. Np.


<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}}
\quad \quad
\quad \quad
\mbox{ i analogicznie dla } \mbox{było-}\mathbf{continue}.
\mbox{ i analogicznie dla } \mbox{było-}\mathbf{continue}</math>
</math>


Zauważmy, że nie musimy zajmowac się przypadkiem, gdy ślad
Nie musimy zajmowac się przypadkiem, gdy ślad powstaje w <math>I_2</math>, bo wybraliśmy podejście małokrokowe.
powstaje w <math> I_2 </math>, bo wybraliśmy podejście mało-krokowe.
Ponadto, nie musimy opisywać instrukcji warunkowej i pętli <math>\mathbf{while}\ </math>,, ponieważ ślad nie może powstać podczas obliczania dozoru!
Ponadto, nie musimy opisywać instrukcji warunkowej i pętli <math> \mathbf{while}\, </math>,
ponieważ ślad nie może powstać podczas oblcizania dozoru!


Wreszcie zobaczmy jak zachowuje się pętla <math> \mathbf{loop}\, </math>:
Wreszcie zobaczmy jak zachowuje się pętla <math>\mathbf{loop}\ </math>,:


<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'}
\quad \quad
\quad \quad
\frac{I, s \,\Longrightarrow\, s', \mbox{było-}\mathbf{continue}}
\frac{I, s \,\Longrightarrow, s', \mbox{było-}\mathbf{continue}}
     {\mathbf{loop}\, I, s \,\Longrightarrow\, \mathbf{loop}\, I, s'}
     {\mathbf{loop}\, I, s \,\Longrightarrow, \mathbf{loop}\, I, s'}
</math>
</math>


Reguły te są prawie identyczne do reguł semantyki naturalnej dla tej
Reguły te są prawie identyczne z regułami semantyki naturalnej dla tej sytuacji!  
sytuacji!  
Natomiast korzystamy z tego, że w podejściu małokrokowym zmiana konfiguracji 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 <math>\mathbf{exit}</math> czy <math>\mathbf{continue}</math> zostało wywołane głęboko wewnątrz <math>I</math>!
Natomiast korzystamy z tego, że w podejściu mało-krokowym zmiana konfiguracji
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
<math> \mathbf{exit} </math> czy <math> \mathbf{continue} </math> zostało wywołane głęboko wewnątrz
<math> I </math>!


Niestety, powyzsze reguły '''nie są poprawne'''!
Niestety powyższe reguły '''nie są poprawne'''!
Dlaczego? Jak zwykle w semantyce małych kroków, wykonując instrukcję
Dlaczego? Jak zwykle w semantyce małych kroków, wykonując instrukcję wewnętrzną "zapominamy" stopniowo, jaka była ona na początku.
wewnętrzną ''zapominamy'' stopniowo jaka była ona na początku.
W związku z tym nie potrafimy poprawnie powrócić do wykonywania pętli <math>\mathbf{loop}\ </math>, po wywołaniu <math>\mathbf{continue}</math>.  
I w związku z tym nie potrafimy poprawnie powrócić do wykonywania
pętli <math> \mathbf{loop}\, </math> po wywołaniu <math> \mathbf{continue} </math>.  


Prostym sposobem poprawienia naszego blędu jest rozszerzenie składni
Prostym sposobem poprawienia naszego błędu jest rozszerzenie składni 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>
<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>


Teraz możemy zapisać dwie powyższe reguły dla <math> \mathbf{loop}\, </math> w poprawnej
Teraz możemy zapisać dwie powyższe reguły dla <math>\mathbf{loop}\ </math>, w poprawnej wersji, pamiętając o tym, że <math>\mbox{było-}\mathbf{exit}</math> i <math>\mbox{było-}\mathbf{continue}</math> pojawią się nie w instrukcji wewnętrznej, ale w jej ''kopii'' umieszczonej przed <math>\,\mathbf{then}\ </math>,:
wersji, pamiętając o tym, że <math> \mbox{było-}\mathbf{exit} </math> i
<math> \mbox{było-}\mathbf{continue} </math> pojawią się nie w instrukcji wewnętrznej,
ale w jej ''kopii'' umieszczonej przed <math> \,\mathbf{then}\, </math>:


<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'}
\quad \quad
\quad \quad
\frac{I', s \,\Longrightarrow\, s', \mbox{było-}\mathbf{continue}}
\frac{I', s \,\Longrightarrow, s', \mbox{było-}\mathbf{continue}}
     {I; \,\mathbf{then}\, \mathbf{loop}\, I, s \,\Longrightarrow\, \mathbf{loop}\, I, s'}
     {I' \,\mathbf{then}\, \mathbf{loop}\, I, s \,\Longrightarrow, \mathbf{loop}\, I, s'}
\quad \quad
\frac{I', s \,\Longrightarrow, s'}
    {I' \,\mathbf{then}\, \mathbf{loop}\, I, s \,\Longrightarrow, \mathbf{loop}\, I, s'}
</math>
</math>


A ponieważ wewnątrz kopii mogą być zagnieżdzone instrukcje
Potrzebujemy też dodatkowej reguły dla obliczeń wewnątrz instrukcji stojącej przed <math>\,\mathbf{then}\ </math>, (w szczególności może ona zawierać zagnieżdzone pętle <math>\mathbf{loop}\ </math>,):
<math> \mathbf{loop}\, </math> potrzebujemy dodatkowej reguły:


<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'}
</math>
</math>


Na koniec zauważmy, że stan <math> s' </math> w  
Na koniec zauważmy, że stan <math>s'</math> w pierwszych dwóch z powyższych reguł nigdy nie jest różny od <math>s</math>. Zatem równoważnie moglibyśmy zamienić <math>s'</math> na <math>s</math> w powyższych dwóch regułach. Ale wtedy okazuje się, <math>s</math> w parze z <math>\mbox{było-}\mathbf{exit}</math> albo <math>\mbox{było-}\mathbf{continue}</math> jest nadmiarowe i może zostać wyeliminowane.
pierwszych dwóch z powyższych trzech reguł nigdy nie jest różny
od <math> s </math>. Zatem równoważnie moglibyśmy zamienić <math> s' </math> na <math> s </math>
w powyższych dwóch regułach. Ale wtedy okazuje się , <math> s </math>
w parze z <math> \mbox{było-}\mathbf{exit} </math> albo <math> \mbox{było-}\mathbf{continue} </math> jest nadmiarowe
i może zostać wyeliminowane.
 
Zatem ostatecznie nasze reguły mogą wyglądać tak:
Zatem ostatecznie nasze reguły mogą wyglądać tak:


<math>
<math>
\mathbf{exit}, s \,\Longrightarrow\, \mbox{było-}\mathbf{exit}
\mathbf{exit}, s \,\Longrightarrow, \mbox{było-}\mathbf{exit}
\quad \quad
\quad \quad
\mathbf{continue}, s \,\Longrightarrow\, \mbox{było-}\mathbf{continue}
\mathbf{continue}, s \,\Longrightarrow, \mbox{było-}\mathbf{continue}
</math>
</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}}
\quad \quad
\quad \quad
\frac{I_1, s \,\Longrightarrow\, \mbox{było-}\mathbf{continue}}
\frac{I_1, s \,\Longrightarrow, \mbox{było-}\mathbf{continue}}
     {I_1;\, I_2, s \,\Longrightarrow\, \mbox{było-}\mathbf{continue}}
     {I_1;\, I_2, s \,\Longrightarrow, \mbox{było-}\mathbf{continue}}
</math>
</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>
<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}
\quad \quad
\quad \quad
\frac{I', s \,\Longrightarrow\, \mbox{było-}\mathbf{continue}}
\frac{I', s \,\Longrightarrow, \mbox{było-}\mathbf{continue}}
     {I; \,\mathbf{then}\, \mathbf{loop}\, I, s \,\Longrightarrow\, \mathbf{loop}\, I, s}
     {I' \,\mathbf{then}\, \mathbf{loop}\, I, s \,\Longrightarrow, \mathbf{loop}\, I, s}
\quad \quad
\frac{I', s \,\Longrightarrow, s'}
    {I' \,\mathbf{then}\, \mathbf{loop}\, I, s \,\Longrightarrow, \mathbf{loop}\, I, s}
</math>
</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'}
</math>
</math>


a zbiór konfiguracji poszerzamy tylko o
a zbiór konfiguracji poszerzamy tylko o dwie nowe konfiguracje <math>\{ \mbox{było-}\mathbf{exit}, \mbox{było-}\mathbf{continue} \}</math>.
<math> \{ \mbox{było-}\mathbf{exit}, \mbox{było-}\mathbf{continue} \} </math>.
 
 


</div></div>


== Zadania domowe ==
== Zadania domowe ==




==== Zadanie 1 ====
{{cwiczenie|1|cw1.dom|


Zaproponuj semantykę mało-krokową języka z zdania 2.
Zaproponuj semantykę małokrokową dla rozszerzeń języka Tiny, które
Czy różni się ona istotnie od semantyki naturalnej?
studiowaliśmy powyżej.
}}




==== Zadanie 2 ====
{{cwiczenie|2|cw2.dom|


Napisz semantyję naturalną dla nieznacznie rozszerzonej wersji instrukcji <math> \mathbf{loop}\, </math>:
Napisz semantykę naturalną dla nieznacznie rozszerzonej wersji instrukcji <math>\mathbf{loop}\ </math>,:


<math>
<math>
I \, ::= \,\,
I \, ::= \,\,
       x: \mathbf{loop}\, I \,\,|\,\,
       x: \mathbf{loop}\, I \,\,|\,\,
       \mathbf{exit} x \,\,|\,\,
       \mathbf{exit}\, x \,\,|\,\,
       \mathbf{continue} x
       \mathbf{continue}\, x
</math>
</math>


Identyfikator <math> x </math> pełni tutaj rolę etykiety przypisanej
Identyfikator <math>x</math> pełni tutaj rolę etykiety związanej z instrukcją <math>\mathbf{loop}\ </math>,, jest też parametrem dwóch pozostałych instrukcji.  
instrukcji <math> \mathbf{loop}\, </math>, jest też parametrem dwóch pozostałych
<math>\mathbf{exit} x</math> kończy teraz najbliższą otaczającą pętlę <math>\mathbf{loop}\ </math>, o etykiecie <math>x</math>. Podobnie <math>\mathbf{continue} x</math> wznawia najbliższą otaczającą pętlę o etykiecie <math>x</math>.  
instrukcji. <math> \mathbf{exit} x </math> kończy teraz najbliższą otaczającą pętlę <math> \mathbf{loop}\, </math>
}}
o etykiecie <math> x </math>. Podobnie <math> \mathbf{continue} x </math> wznawia najbliższą
 
pętlę o etykiecie <math> x </math>. Np. program
{{przyklad|||
}}
Program


x: <math>\mathbf{loop}\ </math>,
  a := 1;
  y: <math>\mathbf{loop}\ </math>,
    <math>\mathbf{exit}</math> x;
    a := a-10;
  a := a+1;
a := a+2;


  x: <math>\mathbf{loop}\,</math>
    a := 1;
    y: <math>\mathbf{loop}\,</math>
      <math>\mathbf{exit}</math> x;
      a := a-10;
    a := a+1;
  a := a+2;


kończy działanie z wartością zmiennej <math>a = 3</math>.
Za pomocą wcięć określiliśmy, do wnętrza której pętli <math>\mathbf{loop}\ </math>, należy każda z trzech ostatnich instrukcji przypisania.
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ę <math>\mathbf{loop}\ </math>,, np. <math>\mathbf{loop}\, I \,\mathbf{end}\mathbf{loop}\ </math>,.


kończy działanie z wartością zmiennej <math> a = 3 </math>.
Zauważmy, że musieliśmy jakoś określić, do wnętrza której pętli
<math> \mathbf{loop}\, </math> 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ę <math> \mathbf{loop}\, </math>,
np. <math> \mathbf{loop}\, I \,\mathbf{end}\mathbf{loop}\, </math>.




==== Zadanie 3 ====
{{cwiczenie|3|cw3.dom|


Napisz semantykę naturalną i mało-krokową dla rozszerzenia
Napisz semantykę naturalną i małokrokową dla rozszerzenia
języka Tiny o wyrażenia z efektami ubocznymi:
języka TINY o wyrażenia z efektami ubocznymi:


<math>
<math>
Linia 621: Linia 551:
</math>
</math>


Obliczenie wyrażenia <math> \,\mathbf{do}\, I \,\mathbf{then}\, e </math> polega na wykonaniu <math> I </math>
Obliczenie wyrażenia <math>\,\mathbf{do}\, I \,\mathbf{then}\, e</math> polega na wykonaniu <math>I</math> a potem na obliczeniu <math>e</math>.  
a potem na obliczeniu <math> e </math>. Wartość wyrażenia <math> x:= e </math> jest taka
Wartość wyrażenia <math>x:= e</math> jest taka, jak wartość wyrażenia <math>e</math> a efektem ubocznym jest podstawienie tej wartości na zmienną <math>x</math>.
jak wartość wyrażenia <math> e </math> a efektem ubocznym jest  
}}
podstawienie tej wartości na zmienną <math> x </math>.

Aktualna wersja na dzień 21:43, 11 wrz 2023

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ą wyrażeń boolowskich i arytmetycznych oraz semantykę błędów wykonania. Wreszcie dodamy nową instrukcję pętli 𝐥𝐨𝐨𝐩 ,, pozwalającą na niestrukturalne przerwanie lub wznowienie iteracji (instrukcje 𝐞𝐱𝐢𝐭 i 𝐜𝐨𝐧𝐭𝐢𝐧𝐮𝐞).


Rozszerzenia semantyki języka Tiny

Ćwiczenie 1

Zdefiniuj znaczenie wyrażeń boolowskich i arytmetycznych w języku TINY w stylu dużych kroków (semantyka naturalna).


Rozwiązanie


Ćwiczenie 2

Rozważ dodatkowo operację dzielenia:

e::=|e1/e2

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


Ćwiczenie 3

Rozszerzmy język TINY o następującą instrukcję pętli:

I::=𝐥𝐨𝐨𝐩I|𝐞𝐱𝐢𝐭|𝐜𝐨𝐧𝐭𝐢𝐧𝐮𝐞

𝐥𝐨𝐨𝐩I to instrukcja pętli, I stanowi instrukcję wewnętrzną. Instrukcja 𝐞𝐱𝐢𝐭 wychodzi z nabliższej otaczającej pętli 𝐥𝐨𝐨𝐩 , i kontynuuje wykonanie programu od pierwszej instrukcji za tą pętlą. Instrukcja 𝐜𝐨𝐧𝐭𝐢𝐧𝐮𝐞 powraca na początek instrukcji wewnętrznej najbliższej otaczającej pętli 𝐥𝐨𝐨𝐩 ,.

Pozważ zarówno semantykę naturalną, jak i semantykę małych kroków.



Rozwiązanie


Rozwiązanie

Zadania domowe

Ćwiczenie 1

Zaproponuj semantykę małokrokową dla rozszerzeń języka Tiny, które studiowaliśmy powyżej.


Ćwiczenie 2

Napisz semantykę naturalną dla nieznacznie rozszerzonej wersji instrukcji 𝐥𝐨𝐨𝐩 ,:

I::=x:𝐥𝐨𝐨𝐩I|𝐞𝐱𝐢𝐭x|𝐜𝐨𝐧𝐭𝐢𝐧𝐮𝐞x

Identyfikator x pełni tutaj rolę etykiety związanej z instrukcją 𝐥𝐨𝐨𝐩 ,, jest też parametrem dwóch pozostałych instrukcji. 𝐞𝐱𝐢𝐭x kończy teraz najbliższą otaczającą pętlę 𝐥𝐨𝐨𝐩 , o etykiecie x. Podobnie 𝐜𝐨𝐧𝐭𝐢𝐧𝐮𝐞x wznawia najbliższą otaczającą pętlę o etykiecie x.

Przykład

Program

x: 𝐥𝐨𝐨𝐩 ,
  a := 1; 
  y: 𝐥𝐨𝐨𝐩 ,
    𝐞𝐱𝐢𝐭 x;
    a := a-10;
  a := a+1;
a := a+2;


kończy działanie z wartością zmiennej a=3. Za pomocą wcięć określiliśmy, do wnętrza której pętli 𝐥𝐨𝐨𝐩 , należy każda z trzech ostatnich instrukcji przypisania. 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. 𝐥𝐨𝐨𝐩I𝐞𝐧𝐝𝐥𝐨𝐨𝐩 ,.


Ćwiczenie 3

Napisz semantykę naturalną i małokrokową dla rozszerzenia języka TINY o wyrażenia z efektami ubocznymi:

e::=|𝐝𝐨I𝐭𝐡𝐞𝐧e|x:=e|x++|

Obliczenie wyrażenia 𝐝𝐨I𝐭𝐡𝐞𝐧e polega na wykonaniu I a potem na obliczeniu e. Wartość wyrażenia x:=e jest taka, jak wartość wyrażenia e a efektem ubocznym jest podstawienie tej wartości na zmienną x.