Semantyka i weryfikacja programów/Ćwiczenia 5: Różnice pomiędzy wersjami
Nie podano opisu zmian |
Nie podano opisu zmian |
||
Linia 1: | Linia 1: | ||
== | == Zawarto¶æ == | ||
Kontynuujemy | Kontynuujemy æwiczenie semantyki naturalnej, | ||
dodaj±c pewne konstrukcje do jêzyka Tiny. | |||
W | W szczególno¶ci rozszerzymy go o deklaracje zmiennych (bloki). | ||
Po raz pierwszy roszdzielimy | Po raz pierwszy roszdzielimy informacjê przechowywan± w konfiguracji | ||
na '' | na ''¶rodowisko'' okre¶laj±ce wi±zanie identyfikatorów i ''stan'' | ||
przechowuj±cy warto¶ci zmiennych. | |||
Bêdzie to przygotowanie do kolejnych zajêæ. | |||
== | == Semantyka naturalna pewnej instrukcji <math>\mathbf{for}\,</math> == | ||
Linia 18: | Linia 18: | ||
Rozszerzamy | Rozszerzamy jêzyk Tiny nastêpuj±co: | ||
<math> | <math> | ||
Linia 28: | Linia 28: | ||
Znaczenie instrukcji <math>\mathbf{for}\, x = e_1 \,\mathbf{to}\, e_2 \,\mathbf{try}\, I_1 \,\mathbf{else}\, I_2</math> | Znaczenie instrukcji <math>\mathbf{for}\, x = e_1 \,\mathbf{to}\, e_2 \,\mathbf{try}\, I_1 \,\mathbf{else}\, I_2</math> | ||
jest | jest nastêpuj±ce. | ||
Obliczamy | Obliczamy warto¶ci wyra¿eñ <math>e_1</math> i <math>e_2</math>. Je¶li pierwsza | ||
z nich jest mniejsza lub równa od drugiej, to podstawiamy | z nich jest mniejsza lub równa od drugiej, to podstawiamy pierwsz± | ||
warto¶æ (warto¶æ wyra¿enia <math>e_1</math>) na zmienn± <math>x</math> i uruchamiamy <math>I_1</math>. | |||
Je¶li w <math>I_1</math> nie zostanie napotkana instrukcja <math>\mathbf{fail}</math>, | |||
koñczymy instrukcjê <math>\mathbf{for}\,</math> i przyracamy warto¶æ zmiennej <math>x</math> | |||
sprzed tej instrukcji. | sprzed tej instrukcji. | ||
Natomiast | Natomiast je¶li w <math>I_1</math> zostanie napotkana instrukcja <math>\mathbf{fail}</math>, | ||
podstawiamy na <math>x</math> | podstawiamy na <math>x</math> kolejn±, o jeden wiêksz± warto¶æ, | ||
przywracamy | przywracamy warto¶ci wszystkich | ||
pozosta³ych zmiennych sprzed instrukcji <math>\mathbf{for}\,</math>, i ponownie | |||
wykonujemy <math>I_1</math>. | wykonujemy <math>I_1</math>. | ||
Powtarzamy w ten sposób | Powtarzamy w ten sposób a¿ <math>I_1</math> zakoñczy siê nie napotkawszy <math>\mathbf{fail}</math>, | ||
albo | albo warto¶æ zmiennej <math>x</math> przekroczy warto¶æ wyra¿enia <math>e_2</math> | ||
obliczon± na pocz±tku. | |||
W pierwszym przypadku | W pierwszym przypadku | ||
koñczymy instrukcjê <math>\mathbf{for}\,</math> i przyracamy warto¶æ zmiennej <math>x</math> | |||
sprzed tej instrukcji. | sprzed tej instrukcji. | ||
W drugim przywracamy | W drugim przywracamy warto¶ci wszystkich zmiennych sprzed instrukcji | ||
<math>\mathbf{for}\,</math> i uruchamiamy <math>I_2</math>. | <math>\mathbf{for}\,</math> i uruchamiamy <math>I_2</math>. | ||
}} | }} | ||
Linia 52: | Linia 52: | ||
{{przyklad||| | {{przyklad||| | ||
Oto | Oto przyk³adowy program: | ||
}} | }} | ||
x := 0; y := 1; | x := 0; y := 1; | ||
<math>\mathbf{for}\,</math> x := 1 \,\mathbf{to}\, 5 <math>\,\mathbf{try}\,</math> | <math>\mathbf{for}\,</math> x := 1 \,\mathbf{to}\, 5 <math>\,\mathbf{try}\,</math> | ||
y := y+1; | y := y+1; | ||
<math>\mathbf{if}\,</math> x | <math>\mathbf{if}\,</math> x <= 4 <math>\,\mathbf{then}\, \mathbf{fail} \,\mathbf{else}\,</math> z:= x | ||
<math>\,\mathbf{else}\, \mathbf{skip}</math> | <math>\,\mathbf{else}\, \mathbf{skip}</math> | ||
Warto¶ci zmiennych po zakoñczeniu programu to: <math>x = 0, y = 2, z = 5</math>. | |||
Linia 71: | Linia 70: | ||
<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"><div class="mw-collapsible-content" style="display:none"> | ||
Bêdziemy pos³ugiwaæ siê jak zwykle tranzycjami postaci: | |||
<math> | <math> | ||
Linia 78: | Linia 77: | ||
Zacznijmy od najprostszego przypadku, gdy nie ma wogóle potrzeby | Zacznijmy od najprostszego przypadku, gdy nie ma wogóle potrzeby | ||
uruchamiania instrukcji | uruchamiania instrukcji wewnêtrznej <math>I_1</math>, poniewa¿ | ||
warto¶æ wyra¿enia <math>e_1</math> jest wiêksza od <math>e_2</math>: | |||
<math> | <math> | ||
Linia 91: | Linia 90: | ||
</math> | </math> | ||
Po prostu uruchamiamy | Po prostu uruchamiamy instrukcjê <math>I_2</math> w stanie <math>s</math>, ignoruj±c | ||
<math>I_1</math>. | <math>I_1</math>. | ||
Kolejny nietrudny przypadek to sytuacja, w której | Kolejny nietrudny przypadek to sytuacja, w której | ||
<math>n_1 \leq n_2</math> a wykonanie instrukcji | <math>n_1 \leq n_2</math> a wykonanie instrukcji wewnêtrznej <math>I_1</math> | ||
koñczy siê sukcesem, tzn. nie nastêpuje wywo³anie instrukcji | |||
<math>\mathbf{fail}</math>. Oto | <math>\mathbf{fail}</math>. Oto regu³a dla tego przypadku: | ||
<math> | <math> | ||
Linia 109: | Linia 108: | ||
</math> | </math> | ||
Tym razem uruchamiamy | Tym razem uruchamiamy instrukcjê <math>I_1</math>, podstawiaj±c | ||
pod | pod zmienn± <math>x</math> warto¶æ <math>n_1</math>. | ||
Zwróæmy uwagê, ¿e po zakoñczeniu <math>I_1</math> przywracamy | |||
warto¶æ zmiennej <math>x</math> sprzed jej wykonania. | |||
Pozosta³ nam trzeci przypadek, gdy <math>n_1 \leq n_2</math> | |||
a wykonanie instrukcji <math>I_1</math> | a wykonanie instrukcji <math>I_1</math> zakoñczy³o siê | ||
wykonaniem instrukcji <math>\mathbf{fail}</math> | wykonaniem instrukcji <math>\mathbf{fail}</math> gdzie¶ wewn±trz <math>I_1</math>. | ||
Aby poprawnie | Aby poprawnie opisaæ takie zdarzenie, potrzebujemy dodatkowych | ||
tranzycji postaci: | tranzycji postaci: | ||
<math> | <math> | ||
I, s \,\longrightarrow\, \mbox{ | I, s \,\longrightarrow\, \mbox{by³o-}\mathbf{fail}. | ||
</math> | </math> | ||
Mówi±c formalnie, poszerzamy zbiór konfiguracji o jeden element | |||
<math>\mbox{ | <math>\mbox{by³o-}\mathbf{fail}</math>. | ||
Zauwa¿my, ¿e po prawej stronie tranzycji nie ma wogóle stanu. | |||
Nie potrzebujemy go dla opisania semantyki instrukcji <math>\mathbf{for}\,</math>: | Nie potrzebujemy go dla opisania semantyki instrukcji <math>\mathbf{for}\,</math>: | ||
je¶li wyst±pi <math>\mathbf{fail}</math>, powtarzamy <math>I_1</math> dla wiêkszej o <math>1</math> warto¶ci | |||
zmiennej <math>x</math>, ale | zmiennej <math>x</math>, ale pozosta³ym zmiennym przywracamy warto¶æ ''sprzed'' | ||
<math>I_1</math>. | <math>I_1</math>. | ||
A | A wiêc za³ó¿my, ¿e | ||
<math>I_1, s[x \mapsto n_1] \,\longrightarrow\, \mbox{ | <math>I_1, s[x \mapsto n_1] \,\longrightarrow\, \mbox{by³o-}\mathbf{fail}.</math> | ||
W takiej sytuacji | W takiej sytuacji powinni¶my przypisaæ <math>n_1 + 1</math> | ||
na | na zmienn± <math>x</math> i spróbowaæ ponownie wykonaæ | ||
<math>I_1</math> przy | <math>I_1</math> przy warto¶ciach wszystkich pozosta³ych | ||
zmiennych takich, jak na | zmiennych takich, jak na pocz±tku instrukcji <math>\mathbf{for}\,</math>. | ||
I | I powtarzaæ ten schemat a¿ do skutku, tzn. a¿ do mementu, | ||
gdy zaistnieje | gdy zaistnieje która¶ z poprzednich dwóch (prostych) sytuacji. | ||
Oto odpowiednia | Oto odpowiednia regu³a: | ||
<math> | <math> | ||
Linia 148: | Linia 147: | ||
e_2, s \,\longrightarrow\, n_2 | e_2, s \,\longrightarrow\, n_2 | ||
\quad | \quad | ||
I_1, s[x \mapsto n_1] \,\longrightarrow\, \mbox{ | I_1, s[x \mapsto n_1] \,\longrightarrow\, \mbox{by³o-}\mathbf{fail} | ||
\quad | \quad | ||
\mathbf{for}\, x = e_1 + 1 \,\mathbf{to}\, e_2 \,\mathbf{try}\, I_1 \,\mathbf{else}\, I_2, s \,\longrightarrow\, s'} | \mathbf{for}\, x = e_1 + 1 \,\mathbf{to}\, e_2 \,\mathbf{try}\, I_1 \,\mathbf{else}\, I_2, s \,\longrightarrow\, s'} | ||
Linia 155: | Linia 154: | ||
</math> | </math> | ||
Zwróæmy uwagê na pewnien niezwykle istotny szczegó³: po zakoñczeniu | |||
wykonania instrukcji <math>\mathbf{for}\, x = e_1 + 1 \,\mathbf{to}\, e_2 \,\mathbf{try}\, I_1 \,\mathbf{else}\, I_2</math> | wykonania instrukcji <math>\mathbf{for}\, x = e_1 + 1 \,\mathbf{to}\, e_2 \,\mathbf{try}\, I_1 \,\mathbf{else}\, I_2</math> | ||
otrzymujemy stan <math>s'</math>, w którym '''nie przywracamy''' | otrzymujemy stan <math>s'</math>, w którym '''nie przywracamy''' warto¶ci | ||
zmiennej <math>x</math>. | zmiennej <math>x</math>. Gdyby¶my tak zrobili, tzn. gdyby¶my zast±pili <math>s' | ||
</math> przez <math>s'[x \mapsto s(x)]</math>, nasze semantyka | </math> przez <math>s'[x \mapsto s(x)]</math>, nasze semantyka by³aby | ||
niepoprawna. Dlaczego? Dlatego, | niepoprawna. Dlaczego? Dlatego, ¿e nie wiemy tak naprawdê, | ||
czy | czy powinni¶my przywracaæ warto¶æ zmiennej <math>x</math> czy nie. | ||
Je¶li ostatecznie nasza instrukcja <math>\mathbf{for}\,</math> zakoñczyla | |||
siê przez bezb³êdne zakoñczenie instrukcji <math>I_1</math> | |||
(przypadek drugi), to | (przypadek drugi), to powinni¶my to zrobiæ; | ||
ale | ale je¶li zakoñczy³a siê wykonaniem instrukcji <math>I_2</math> | ||
(przypadek pierwszy), | (przypadek pierwszy), | ||
to | to powinni¶my pozostawiæ warto¶æ zmiennej <math>x</math> tak±, | ||
jaka jest ona po | jaka jest ona po zakoñczeniu <math>I_2</math>. | ||
A zatem w | A zatem w powy¿szej regule dla przypadku trzeciego | ||
nie przywracamy | nie przywracamy warto¶ci zmiennej <math>x</math>; je¶li by³o | ||
to konieczne, to | to konieczne, to zosta³o ju¿ wykonane ,,g³êbiej", | ||
dziêki regule dla przypadku drugiego oraz dziêki temu, | |||
¿e instrukcja <math>\mathbf{for}\, x = e_1 + 1 \,\mathbf{to}\, e_2 \,\mathbf{try}\, I_1 \,\mathbf{else}\, I_2</math> | |||
wykonywana jest w orginalnym stanie <math>s</math>, | wykonywana jest w orginalnym stanie <math>s</math>, | ||
a nie w stanie, w którym | a nie w stanie, w którym koñczy siê <math>I_1</math> | ||
(tego ostatniego stanu nawet nie znamy). | (tego ostatniego stanu nawet nie znamy). | ||
Jeszcze jeden drobiazg: zamiast <math>e_1 {+} 1</math> w | Jeszcze jeden drobiazg: zamiast <math>e_1 {+} 1</math> w | ||
<math>\mathbf{for}\, x = e_1 + 1 \,\mathbf{to}\, e_2 \,\mathbf{try}\, I_1 \,\mathbf{else}\, I_2, s \,\longrightarrow\, s'</math> | <math>\mathbf{for}\, x = e_1 + 1 \,\mathbf{to}\, e_2 \,\mathbf{try}\, I_1 \,\mathbf{else}\, I_2, s \,\longrightarrow\, s'</math> | ||
w regule | w regule powy¿ej, mogliby¶my podstawiæ policzon± ju¿ | ||
warto¶æ, czyli <math>n_1 {+} 1</math>. | |||
Na | Na zakoñczenie prezentujemy regu³y niebêdne do tego, | ||
aby | aby wygenerowaæ <math>\mbox{by³o-}\mathbf{fail}</math>: | ||
<math> | <math> | ||
\mathbf{fail}, s \,\longrightarrow\, \mbox{ | \mathbf{fail}, s \,\longrightarrow\, \mbox{by³o-}\mathbf{fail} | ||
</math> | </math> | ||
oraz aby | oraz aby wyst±pienie <math>\mathbf{fail}</math> umiejscowione gdzie¶ ,,g³êboko" | ||
zosta³o rozpropagowane do najbli¿szej otaczaj±cej | |||
instrukcji <math>\mathbf{for}\,</math>. | instrukcji <math>\mathbf{for}\,</math>. | ||
Je¶li pojawi³ siê <math>\mathbf{fail}</math>, powinni¶my zaniechaæ dalszego | |||
wykonania instrukcji a w przypadku | wykonania instrukcji a w przypadku pêtli, powinni¶my | ||
zaniechaæ dalszego iterowania tej pêtli. | |||
Oto odpowiednie | Oto odpowiednie regu³y: | ||
<math> | <math> | ||
\frac{I_1, s \,\longrightarrow\, \mbox{ | \frac{I_1, s \,\longrightarrow\, \mbox{by³o-}\mathbf{fail}} | ||
{I_1;\, I_2, s \,\longrightarrow\, \mbox{ | {I_1;\, I_2, s \,\longrightarrow\, \mbox{by³o-}\mathbf{fail}} | ||
\quad \quad | \quad \quad | ||
\frac{I_1, s \,\longrightarrow\, s' \quad \quad I_2, s' \,\longrightarrow\, \mbox{ | \frac{I_1, s \,\longrightarrow\, s' \quad \quad I_2, s' \,\longrightarrow\, \mbox{by³o-}\mathbf{fail}} | ||
{I_1;\, I_2, s \,\longrightarrow\, \mbox{ | {I_1;\, I_2, s \,\longrightarrow\, \mbox{by³o-}\mathbf{fail}} | ||
</math> | </math> | ||
<math> | <math> | ||
\frac{b, s \,\longrightarrow\, \mathbf{true} \quad \quad I_1, s \,\longrightarrow\, \mbox{ | \frac{b, s \,\longrightarrow\, \mathbf{true} \quad \quad I_1, s \,\longrightarrow\, \mbox{by³o-}\mathbf{fail}} | ||
{\mathbf{if}\, b \,\mathbf{then}\, I_1 \,\mathbf{else}\, I_2, s \,\longrightarrow\, \mbox{ | {\mathbf{if}\, b \,\mathbf{then}\, I_1 \,\mathbf{else}\, I_2, s \,\longrightarrow\, \mbox{by³o-}\mathbf{fail}} | ||
\quad \quad | \quad \quad | ||
\mbox{ i analogicznie gdy } b, s \,\longrightarrow\, \mathbf{false} | \mbox{ i analogicznie gdy } b, s \,\longrightarrow\, \mathbf{false} | ||
Linia 214: | Linia 213: | ||
<math> | <math> | ||
\frac{b, s \,\longrightarrow\, \mathbf{true} \quad \quad I, s \,\longrightarrow\, \mbox{ | \frac{b, s \,\longrightarrow\, \mathbf{true} \quad \quad I, s \,\longrightarrow\, \mbox{by³o-}\mathbf{fail}} | ||
{\mathbf{while}\, b \,\mathbf{do}\, I, s \,\longrightarrow\, \mbox{ | {\mathbf{while}\, b \,\mathbf{do}\, I, s \,\longrightarrow\, \mbox{by³o-}\mathbf{fail}} | ||
\quad \quad | \quad \quad | ||
\frac{b, s \,\longrightarrow\, \mathbf{true} \quad \quad I, s \,\longrightarrow\, s' \quad \quad | \frac{b, s \,\longrightarrow\, \mathbf{true} \quad \quad I, s \,\longrightarrow\, s' \quad \quad | ||
\mathbf{while}\, b \,\mathbf{do}\, I, s' \,\longrightarrow\, \mbox{ | \mathbf{while}\, b \,\mathbf{do}\, I, s' \,\longrightarrow\, \mbox{by³o-}\mathbf{fail}} | ||
{\mathbf{while}\, b \,\mathbf{do}\, I, s \,\longrightarrow\, \mbox{ | {\mathbf{while}\, b \,\mathbf{do}\, I, s \,\longrightarrow\, \mbox{by³o-}\mathbf{fail}} | ||
</math> | </math> | ||
Widaæ podobieñstwo do analogicznych regu³ dla | |||
pêtli <math>\mathbf{loop}\, I</math>, któr± zajmowali¶my siê na wcze¶niejszych | |||
zajêciach. | |||
Zauwa¿my, ¿e jesli <math>\mathbf{fail}</math> zosta³o wykonane poza jak±kolwiek | |||
pêtl± <math>\mathbf{for}\,</math>, to program ,,zakoñczy siê" w konfiguracji | |||
<math>\mbox{ | <math>\mbox{by³o-}\mathbf{fail}</math>. Mo¿emy zatem tê w³a¶nie konfiguracjê | ||
uznaæ za konfiguracjê koñcow±, informuj±c± o pora¿ce | |||
wykonania programu. | wykonania programu. | ||
</div></div> | </div></div> | ||
}} | }} | ||
== Semantyka naturalna bloków == | |||
{{cwiczenie|2 (bloki i deklaracje zmiennych)|cw2| | {{cwiczenie|2 (bloki i deklaracje zmiennych)|cw2| | ||
Rozszerz | Rozszerz semantykê jêzyka Tiny o deklaracjê zmiennej: | ||
<math> | <math> | ||
Linia 246: | Linia 248: | ||
</math> | </math> | ||
Zasiêgiem zmiennej <math>x</math> jest instrukcja <math>I</math> | |||
czyli | czyli wnêtrze bloku, w którym jest zadeklarowana. | ||
Zak³adamy zwyk³e (statyczne) regu³y widoczno¶ci, przes³aniania, itp. | |||
}} | }} | ||
Linia 256: | Linia 258: | ||
<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"><div class="mw-collapsible-content" style="display:none"> | ||
''' | '''Rozwi±zanie 1 (tylko stan)''' | ||
<br> | <br> | ||
Oczywi¶cie powinni¶my odró¿niaæ zmienne zadeklarowane (i zarazem | |||
zainicjowane) od tych niezadeklarowanych. | zainicjowane) od tych niezadeklarowanych. | ||
Zatem przyjmijmy, | Zatem przyjmijmy, ¿e | ||
<math>\mathbf{State} = \mathbf{Var} \to_{\mathrm{fin}} \mathbf{Num}</math>. | <math>\mathbf{State} = \mathbf{Var} \to_{\mathrm{fin}} \mathbf{Num}</math>. | ||
Zachowujemy wszystkie | Zachowujemy wszystkie regu³y semantyczne dla jêzyka Tiny | ||
i dodajemy | i dodajemy jedn± now±: | ||
<math> | <math> | ||
Linia 273: | Linia 275: | ||
</math> | </math> | ||
mówi±c±, ¿e instrukcja wewnêtrzna <math>I</math> ewaluowana jest | |||
w stanie, w którym dodatkowo zaznaczono | w stanie, w którym dodatkowo zaznaczono warto¶æ zmiennej <math>x</math> | ||
równ± warto¶ci, do której oblicza siê <math>e</math>. | |||
Oczywi¶cie takie rozwi±zanie jest niepoprawne, gdy¿ warto¶æ | |||
zmiennej <math>x</math> pozostaje w stanie nawet po | zmiennej <math>x</math> pozostaje w stanie nawet po wyj¶ciu z bloku | ||
(,,wycieka" z bloku). | (,,wycieka" z bloku). | ||
Musimy | Musimy dodaæ ,,dealokacjê" zmiennej <math>x</math>: | ||
<math> | <math> | ||
Linia 287: | Linia 289: | ||
</math> | </math> | ||
I znów napotykamy podobnie | I znów napotykamy podobnie trudno¶ci jak na wcze¶niejszych zajêciach: | ||
powy¿sza regu³a nie obejmuje przypadku, gdy <math>s(x)</math> jest | |||
nieokre¶lone. | |||
I | I choæ mogliby¶my naprawiæ ten mankament podobnie jak kiedy¶ | ||
(co pozostawiamy Czytelnikowi), istnieje inne, bardzo eleganckie | (co pozostawiamy Czytelnikowi), istnieje inne, bardzo eleganckie | ||
i elastyczne | i elastyczne rozwi±zanie tego problemu, które teraz omówimy. | ||
<br> | <br> | ||
''' | '''Rozwi±zanie 2 (stan i ¶rodowisko)''' | ||
<br> | <br> | ||
Podstawowy | Podstawowy pomys³ polega na rozdzielenie informacji przechowywanej | ||
dotychczas w stanie na dwa ,,etapy". | dotychczas w stanie na dwa ,,etapy". | ||
Pierwszy z nich, odwzorowuje identyfikatory zmiennych na ''lokacje'', a drugi | Pierwszy z nich, odwzorowuje identyfikatory zmiennych na ''lokacje'', a drugi | ||
lokacje na | lokacje na warto¶ci. | ||
Mamy | Mamy wiêc ''¶rodowiska'' <math>E \in \mathbf{Env}</math>, bêd±ce funkcjami czê¶ciowymi z <math>\mathbf{Var}</math> | ||
do <math>\mathbf{Loc}</math>, zbioru lokacji: | do <math>\mathbf{Loc}</math>, zbioru lokacji: | ||
Linia 310: | Linia 312: | ||
</math> | </math> | ||
oraz stany, | oraz stany, bêd±ce teraz funkcjami czê¶ciowymi z <math>\mathbf{Loc}</math> do <math>\mathbf{Num}</math>: | ||
<math> | <math> | ||
Linia 316: | Linia 318: | ||
</math> | </math> | ||
Dla | Dla jednoznaczno¶ci u¿ywamy innej nazwy (<math>\mathbf{Store}</math>) ale bêdziemy | ||
zwykle | zwykle u¿ywaæ symbolu <math>s, s', s_1, \ldots \in \mathbf{Store}</math> itp. do nazywania stanów. | ||
Intuicyjnie | Intuicyjnie mo¿na my¶leæ o lokacjach w pamiêci | ||
operacyjnej maszyny. | operacyjnej maszyny. ¦rodowisko zawiera informacjê o lokacji, w której | ||
przechowywana jest | przechowywana jest warto¶æ danej zmiennej | ||
a stan opisuje | a stan opisuje w³a¶nie zawarto¶æ u¿ywanych lokacji. | ||
Zak³adamy przy tym, ¿e mamy do dyspozycji nieskoñczony zbiór | |||
lokacji <math>\mathbf{Loc} = \{ l_0, l_1, \ldots \}</math> i | lokacji <math>\mathbf{Loc} = \{ l_0, l_1, \ldots \}</math> i ¿e | ||
w | w ka¿dym momencie tylko skoñczenie wiele spo¶ród nich jest | ||
wykorzystywane. | wykorzystywane. | ||
Formalnie | Formalnie mowi±c, dziedzina funkcji czê¶ciowej <math>s</math> jest zawsze skoñczona. | ||
Daje nam to | Daje nam to pewno¶æ, ¿e zawsze jest jaka¶ nieu¿ywana lokacja. | ||
¦rodowisko pocz±tkowe, w którym uruchamiany | |||
bêdzie program, bêdzie z regu³y puste. | |||
Ponadto obraz funkcji | Ponadto obraz funkcji czê¶ciowej <math>E</math> | ||
bêdzie zawsze zawarty w zbiorze aktualnie u¿ywanych lokacji, | |||
czyli zawarty w dziedzinie funkcji | czyli zawarty w dziedzinie funkcji czê¶ciowej <math>s</math>, oznaczanej | ||
<math>\mathrm{dom}(s)</math>. | <math>\mathrm{dom}(s)</math>. | ||
Po¿ytek z tego podzia³u na dwa etapy bêdzie taki, ¿e | |||
bêdziemy umieli ³atwo i elastycznie opisywaæ deklaracje zmiennych, | |||
przes³anianie identyfikatorów, itp. | |||
Tranzycje | Tranzycje bêd± teraz postaci: | ||
<math> | <math> | ||
Linia 346: | Linia 348: | ||
</math> | </math> | ||
czyli instrukcja <math>I</math> | czyli instrukcja <math>I</math> bêdzie modyfikowaæ stan ale nie bêdzie | ||
zmieniaæ ¶rodowiska <math>E</math>. Dla czytelno¶ci bêdziemy zapisywaæ | |||
nasze | nasze regu³y w nastêpuj±cy sposób: | ||
<math> | <math> | ||
Linia 354: | Linia 356: | ||
</math> | </math> | ||
podkre¶laj±c w ten sposób, ¿e ¶rodowisko nie ulega zmianie. | |||
Ale | Ale nale¿y pamiêtaæ, ¿e konfiguracja, w której ,,uruchamiamy" | ||
instrukcjê <math>I</math> sk³ada siê naprawdê z pary <math>(E, s)</math>. | |||
Deklaruj±c now± zmienn± <math>x</math> dodamy po prostu do <math>E</math> parê | |||
<math>(x, l)</math>, gdzie <math>l</math> jest | <math>(x, l)</math>, gdzie <math>l</math> jest now±, nieu¿ywan± dotychczas lokacj±. | ||
Dla wygody zapisu | Dla wygody zapisu za³ó¿my, ¿e mamy do dyspozycji funkcjê | ||
funkcjê | |||
<math> | <math> | ||
Linia 367: | Linia 369: | ||
</math> | </math> | ||
która zwraca | która zwraca jak±¶ now±, nieu¿ywan± lokacjê. Formalnie wymagamy, by | ||
<math> | <math> | ||
Linia 373: | Linia 375: | ||
</math> | </math> | ||
Dla ilustracji popatrzmy na | Dla ilustracji popatrzmy na przyk³adow± regu³ê dla deklaracji. | ||
<math> | <math> | ||
Linia 382: | Linia 384: | ||
</math> | </math> | ||
Zauwa¿my, ¿e stan <math>s'</math> po zakoñczeniu instrukcji | |||
<math>\mathbf{begin}\, \mathbf{var}\, x=e;\, I \,\mathbf{end}</math> zawiera | <math>\mathbf{begin}\, \mathbf{var}\, x=e;\, I \,\mathbf{end}</math> zawiera informacjê o zmiennej | ||
lokalnej <math>x</math>, tzn. <math>s(l)</math> jest | lokalnej <math>x</math>, tzn. <math>s(l)</math> jest okre¶lone. | ||
Ale lokacja <math>l</math> jest ,, | Ale lokacja <math>l</math> jest ,,nieosi±galna" w ¶rodowisku | ||
<math>E</math>, | <math>E</math>, gdy¿ para <math>x \mapsto l</math> zosta³a dodana tylko do | ||
¶rodowiska, w którym ewaluuje siê wnêtrze bloku, a ¶rodowisko | |||
<math>E</math> | <math>E</math> ca³ego bloku nie jest modyfikowane. | ||
Poni¿ej przedstawiamy regu³y dla pozosta³ych instrukcji. | |||
Przede wszystkim | Przede wszystkim z³o¿enie sekwencyjne: | ||
<math> | <math> | ||
Linia 400: | Linia 402: | ||
</math> | </math> | ||
Regu³a ta uzmys³awia nam ró¿nicê pomiêdzy ¶rodowiskiem a stanem: | |||
¶rodowisko pozostaje to samo, gdy przechodzimy od jednej instrukcji do | |||
nastêpnej, a stan oczywi¶cie ewoluuje wraz ze zmieniaj±cymi siê | |||
warto¶ciami zmiennych. | |||
Regu³y dla przypisania, instrukcji warunkowej i pêtli | |||
nie | nie przedstawiaj± ¿adnych nowych trudno¶ci. | ||
Musimy tylko najpierw | Musimy tylko najpierw ustaliæ postaæ regu³ dla wyra¿eñ: | ||
<math> | <math> | ||
Linia 413: | Linia 415: | ||
</math> | </math> | ||
która jest | która jest zupe³nie naturalna w naszym podej¶ciu opartym o ¶rodowiska | ||
i stany. | i stany. | ||
Regu³y mog± wygl±daæ np. tak: | |||
<math> | <math> | ||
Linia 441: | Linia 443: | ||
</math> | </math> | ||
Regu³y dla wyra¿eñ s± oczywiste: | |||
<math> | <math> | ||
Linia 450: | Linia 452: | ||
</math> | </math> | ||
i tak dalej -- pomijamy | i tak dalej -- pomijamy pozosta³e regu³y. | ||
Linia 457: | Linia 459: | ||
<br> | <br> | ||
Przypomnijmy sobie | Przypomnijmy sobie semantykê bloku | ||
<math> | <math> | ||
Linia 466: | Linia 468: | ||
</math> | </math> | ||
i zastanówmy | i zastanówmy siê, jak ,,posprz±taæ" po zakoñczeniu wykonania bloku, | ||
tzn. | tzn. zwolniæ lokacjê <math>l</math>, która by³a u¿ywana tylko w tym bloku | ||
i w | i w zwi±zku z tym nie bêdzie ju¿ potrzebne. | ||
Oznacza³oby to przywrócenie lokacji <math>l</math> do puli wolnych | |||
( | (nieu¿ywanych) lokacji. | ||
Zmodyfikowana | Zmodyfikowana regu³a dla instrukcji bloku powinna wygl±daæ mniej wiêcej tak: | ||
<math> | <math> | ||
Linia 482: | Linia 484: | ||
gdzie <math>\bar{s}</math> to stan <math>s''</math> ,,okrojony" do dziedziny stanu <math>s</math>. | gdzie <math>\bar{s}</math> to stan <math>s''</math> ,,okrojony" do dziedziny stanu <math>s</math>. | ||
Powinni¶my po prostu przywróciæ nieokre¶lono¶æ stanu dla lokacji | |||
<math>l</math>. | <math>l</math>. | ||
Natomiast | Natomiast oczywi¶cie nie ma potrzeby dealokownia ¶rodowiska! | ||
Oto | Oto rozwi±zanie: | ||
<math> | <math> | ||
Linia 500: | Linia 502: | ||
{{cwiczenie|1|cw1.dom| | |||
Napisz | Napisz semantykê naturaln± dla nastêpuj±cego | ||
rozszerzenia | rozszerzenia jêzyka Tiny: | ||
<math> | <math> | ||
Linia 518: | Linia 520: | ||
</math> | </math> | ||
Instrukcja <math>\mathbf{throw}\, x</math> oznacza podniesienie | Instrukcja <math>\mathbf{throw}\, x</math> oznacza podniesienie wyj±tku o nazwie <math>x</math>. | ||
Instrukcja <math>I = \,\mathbf{try}\, I_1 \,\mathbf{catch}\, exc\, I_2</math> wykonuje <math>I_1</math>. | Instrukcja <math>I = \,\mathbf{try}\, I_1 \,\mathbf{catch}\, exc\, I_2</math> wykonuje <math>I_1</math>. | ||
Je¶li podczas wykonania <math>I_1</math> zostanie podniesiony wyj±tej <math>x | |||
</math>, i <math>exc = x</math> albo <math>exc = \mathbf{any}</math>, to | </math>, i <math>exc = x</math> albo <math>exc = \mathbf{any}</math>, to nastêpuje przerwanie <math> | ||
I_1</math> i sterowanie zostaje przeniesione do <math>I_2</math> | I_1</math> i sterowanie zostaje przeniesione do <math>I_2</math> | ||
( | (nastêpuje ''obs³uga wyj±tku''). | ||
Je¶li za¶ podczas wykonania <math>I_1</math> zostanie podniesiony wyj±tej <math>x | |||
</math> oraz <math>exc \neq x</math> i <math>exc \neq \mathbf{any}</math>, to | </math> oraz <math>exc \neq x</math> i <math>exc \neq \mathbf{any}</math>, to obs³uga wyj±tku | ||
przekazana jest do | przekazana jest do najbli¿szej instrukcji <math>\,\mathbf{try}\,</math> otaczaj±cej <math>I | ||
</math>. | </math>. | ||
Umawiamy | Umawiamy siê, ¿e <math>\,\mathbf{try}\, I_1 \,\mathbf{catch}\, exc\, I_2</math> ''otacza'' <math>I_1</math> | ||
i wszystkie instrukcje | i wszystkie instrukcje wewn±trz <math>I_1</math>, | ||
ale ''nie'' otacza <math>I_2</math>. | ale ''nie'' otacza <math>I_2</math>. | ||
}} | |||
{{cwiczenie|2|cw2.dom| | |||
Zaproponuj | Zaproponuj modyfikacjê semantyki, w której deklaracja | ||
jest wykonywana ,,równolegle", analogicznie do przypisania | jest wykonywana ,,równolegle", analogicznie do przypisania | ||
równoleg³ego. Przy takiej semantyce kolejno¶æ poszczególnych | |||
deklaracji powinna | deklaracji powinna byæ nieistotna. | ||
}} |
Wersja z 08:02, 9 sie 2006
Zawarto¶æ
Kontynuujemy æwiczenie semantyki naturalnej, dodaj±c pewne konstrukcje do jêzyka Tiny. W szczególno¶ci rozszerzymy go o deklaracje zmiennych (bloki). Po raz pierwszy roszdzielimy informacjê przechowywan± w konfiguracji na ¶rodowisko okre¶laj±ce wi±zanie identyfikatorów i stan przechowuj±cy warto¶ci zmiennych. Bêdzie to przygotowanie do kolejnych zajêæ.
Semantyka naturalna pewnej instrukcji
Ćwiczenie 1
Rozszerzamy jêzyk Tiny nastêpuj±co:
Znaczenie instrukcji jest nastêpuj±ce. Obliczamy warto¶ci wyra¿eñ i . Je¶li pierwsza z nich jest mniejsza lub równa od drugiej, to podstawiamy pierwsz± warto¶æ (warto¶æ wyra¿enia ) na zmienn± i uruchamiamy . Je¶li w nie zostanie napotkana instrukcja , koñczymy instrukcjê i przyracamy warto¶æ zmiennej sprzed tej instrukcji. Natomiast je¶li w zostanie napotkana instrukcja , podstawiamy na kolejn±, o jeden wiêksz± warto¶æ, przywracamy warto¶ci wszystkich pozosta³ych zmiennych sprzed instrukcji , i ponownie wykonujemy . Powtarzamy w ten sposób a¿ zakoñczy siê nie napotkawszy , albo warto¶æ zmiennej przekroczy warto¶æ wyra¿enia obliczon± na pocz±tku. W pierwszym przypadku koñczymy instrukcjê i przyracamy warto¶æ zmiennej sprzed tej instrukcji. W drugim przywracamy warto¶ci wszystkich zmiennych sprzed instrukcji i uruchamiamy .
Przykład
Oto przyk³adowy program:
x := 0; y := 1; x := 1 \,\mathbf{to}\, 5 y := y+1; x <= 4 z:= x
Warto¶ci zmiennych po zakoñczeniu programu to: .
Rozwiązanie
Semantyka naturalna bloków
Ćwiczenie 2 (bloki i deklaracje zmiennych)
Rozszerz semantykê jêzyka Tiny o deklaracjê zmiennej:
Zasiêgiem zmiennej jest instrukcja czyli wnêtrze bloku, w którym jest zadeklarowana. Zak³adamy zwyk³e (statyczne) regu³y widoczno¶ci, przes³aniania, itp.
Rozwiązanie
Zadania domowe
Ćwiczenie 1
Napisz semantykê naturaln± dla nastêpuj±cego rozszerzenia jêzyka Tiny:
Parser nie mógł rozpoznać (nieznana funkcja „\ldotes”): {\displaystyle I \, ::= \,\, \ldotes \,\,|\,\, \mathbf{throw}\, x \,\,|\,\, \,\mathbf{try}\, I_1 \,\mathbf{catch}\, exc\, I_2 }
Instrukcja oznacza podniesienie wyj±tku o nazwie . Instrukcja wykonuje . Je¶li podczas wykonania zostanie podniesiony wyj±tej , i albo , to nastêpuje przerwanie i sterowanie zostaje przeniesione do (nastêpuje obs³uga wyj±tku). Je¶li za¶ podczas wykonania zostanie podniesiony wyj±tej oraz i , to obs³uga wyj±tku przekazana jest do najbli¿szej instrukcji otaczaj±cej . Umawiamy siê, ¿e otacza i wszystkie instrukcje wewn±trz , ale nie otacza .
Ćwiczenie 2
Zaproponuj modyfikacjê semantyki, w której deklaracja jest wykonywana ,,równolegle", analogicznie do przypisania równoleg³ego. Przy takiej semantyce kolejno¶æ poszczególnych deklaracji powinna byæ nieistotna.