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 7 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ą
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 oraz semantykę błędów wykonania.
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>).
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>).




Linia 15: Linia 12:
{{cwiczenie|1|cw1|
{{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).
}}
}}




{{rozwiazanie||roz1|


<div class="mw-collapsible mw-made=collapsible mw-collapsed"><div class="mw-collapsible-content" style="display:none">
<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 61: Linia 57:
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{false} \}</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 76: Linia 68:
</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 93: 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 110: 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 129: 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>
\frac{e_1, s \,\longrightarrow\, n_1 \quad \quad e_2, s \,\longrightarrow\, n_2 \quad \quad n_1 \leq n_2}
    {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>
<math>
Linia 140: 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>
Linia 152: Linia 145:
</math>
</math>


Czyli jeśli którekolwiek z podwyrażeń daje wynik <math>\mathbf{false}</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 162: 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>
</div></div>
}}
 




Linia 182: 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ł.
}}
}}




{{rozwiazanie||roz2|
<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 mw-made=collapsible mw-collapsed"><div class="mw-collapsible-content" style="display:none">
<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 202: 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
(duże i małe kroki):


<math>
<math>
Linia 211: Linia 196:
{e_1 / e_2, s \,\longrightarrow\, \mathtt{Blad}}
{e_1 / e_2, s \,\longrightarrow\, \mathtt{Blad}}
\quad \quad
\quad \quad
e_1 / 0, s \,\Longrightarrow\, \mathtt{Blad}.
e_1 / 0, s \,\Longrightarrow, \mathtt{Blad}</math>
</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>
Linia 227: Linia 207:
{e_1 / e_2, s \,\longrightarrow\, \mathtt{Blad}, s}
{e_1 / e_2, s \,\longrightarrow\, \mathtt{Blad}, s}
\quad \quad
\quad \quad
e_1 / 0, s \,\Longrightarrow\, \mathtt{Blad}, s
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 287: Linia 263:
</math>
</math>


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




{{cwiczenie|3|cw3|
{{cwiczenie|3|cw3|


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


<math>
<math>
Linia 310: Linia 282:


<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 otaczającej 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>,.
Instrukcja <math>\mathbf{continue}</math> powraca na początek instrukcji wewnętrznej
najbliższej otaczającej pętli <math>\mathbf{loop}\,</math>.


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




{{rozwiazanie|(semantyka naturalna)|roz3.1|


<div class="mw-collapsible mw-made=collapsible mw-collapsed"><div class="mw-collapsible-content" style="display:none">


Dodamy do reguł semantyki naturalnej dla języka Tiny
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
kilka nowych reguł opisujących nową konstrukcję języka
<span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie</span>
i jej ,,interakcję\'' z pozostałymi konstrukcjami.
<div class="mw-collapsible-content" style="display:none">
 
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
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
'''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>?
<math>\mathbf{continue}</math> w konfiguracji <math>s, \mbox{było-}\mathbf{exit}</math>
Czy instrukcje <math>\mathbf{exit}</math> i <math>\mathbf{continue}</math> będą faktycznie wykonywane w takich konfiguracjach?
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 366: 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 392: 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
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>:
Oto odpowiednie reguły dla <math>\mbox{było-}\mathbf{exit}</math>:


Linia 432: Linia 377:


Pominęliśmy zupełnie analogiczne reguły dla <math>\mbox{było-}\mathbf{continue}</math>.
Pominęliśmy zupełnie analogiczne reguły dla <math>\mbox{było-}\mathbf{continue}</math>.
Zauważmy, że dla pętli <math>\mathbf{while}\,</math> nie rozpatrujemy przypadku,
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.
gdy dozór <math>b</math> oblicza się do <math>\mathbf{false}</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>
</div></div>
}}




{{rozwiazanie|(małe kroki)|roz3.2|


<div class="mw-collapsible mw-made=collapsible mw-collapsed"><div class="mw-collapsible-content" style="display:none">
<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>


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 obliczania 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 powyższe 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
\quad \quad
\frac{I', s \,\Longrightarrow\, s'}
\frac{I', s \,\Longrightarrow, s'}
     {I; \,\mathbf{then}\, \mathbf{loop}\, I, s \,\Longrightarrow\, \mathbf{loop}\, I, s'}
     {I' \,\mathbf{then}\, \mathbf{loop}\, I, s \,\Longrightarrow, \mathbf{loop}\, I, s'}
</math>
</math>


Potrzebujemy też dodatkowej reguły dla obliczeń wewnątrz instrukcji
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>,):
stojącej przed <math>\,\mathbf{then}\,</math> (w szczególności może ona zawierać  
zagnieżdzone pętle <math>\mathbf{loop}\,</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>


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 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
\quad \quad
\frac{I', s \,\Longrightarrow\, s'}
\frac{I', s \,\Longrightarrow, s'}
     {I; \,\mathbf{then}\, \mathbf{loop}\, I, s \,\Longrightarrow\, \mathbf{loop}\, I, 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 dwie nowe konfiguracje
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>
</div></div>
}}


== Zadania domowe ==
== Zadania domowe ==
Linia 591: Linia 499:
{{cwiczenie|1|cw1.dom|
{{cwiczenie|1|cw1.dom|


Zaproponuj semantykę mało-krokową dla rozszerzeń języka Tiny, które
Zaproponuj semantykę małokrokową dla rozszerzeń języka Tiny, które
studiowaliśmy powyżej.
studiowaliśmy powyżej.
}}
}}
Linia 598: Linia 506:
{{cwiczenie|2|cw2.dom|
{{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>
Linia 607: Linia 515:
</math>
</math>


Identyfikator <math>x</math> pełni tutaj rolę etykiety związanej z
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.  
instrukcją <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ą
otaczającą pętlę o etykiecie <math>x</math>.  
}}
}}


Linia 618: Linia 523:
Program
Program


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


kończy działanie z wartością zmiennej <math>a = 3</math>.
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
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.  
<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>,.
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>.




Linia 639: Linia 540:
{{cwiczenie|3|cw3.dom|
{{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 650: 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.