Semantyka i weryfikacja programów/Ćwiczenia 1: Różnice pomiędzy wersjami
Nie podano opisu zmian |
Nie podano opisu zmian |
||
Linia 1: | Linia 1: | ||
== Zawarto¶æ == | |||
Tematem tych zajêæ jest semantyka operacyjna wyra¿eñ (ma³e kroki). | |||
== Semantyka operacyjna wyra¿eñ == | |||
{{cwiczenie|1|cw1| | {{cwiczenie|1|cw1| | ||
Rozwa¿my bardzo prosty jêzyk wyra¿eñ, którego sk³adnia opisana jest | |||
nastêpuj±c± gramatyk±: | |||
<math> | <math> | ||
Linia 30: | Linia 30: | ||
</math> | </math> | ||
Wynikiem | Wynikiem wyra¿enienia warunkowego <math>\mathbf{if}\, e_1 \,\mathbf{then}\, e_2 \,\mathbf{else}\, e_3</math> | ||
jest | jest warto¶æ wyra¿enia <math>e_2</math>, o ile wyra¿enie | ||
<math>e_1</math> oblicza | <math>e_1</math> oblicza siê do warto¶ci ró¿nej od zera; w przeciwnym | ||
przypadku wynikiem jest | przypadku wynikiem jest warto¶æ wyra¿enia <math>e_3</math>. | ||
Zaproponuj | Zaproponuj semantykê operacyjn± (ma³e kroki) dla tego jêzyka. | ||
}} | }} | ||
Linia 44: | Linia 44: | ||
Zacznijmy od ustalenia notacji i dziedzin syntaktycznych. | Zacznijmy od ustalenia notacji i dziedzin syntaktycznych. | ||
Niech <math>\mathbf{Num}</math> oznacza zbiór | Niech <math>\mathbf{Num}</math> oznacza zbiór sta³ych liczbowych, | ||
<math>n \in \mathbf{Num} = \{ 0, 1, \ldots \}</math>. | <math>n \in \mathbf{Num} = \{ 0, 1, \ldots \}</math>. | ||
Podobnie, niech <math>\mathbf{Var}</math> oznacza zbiór identyfikatorów, które | Podobnie, niech <math>\mathbf{Var}</math> oznacza zbiór identyfikatorów, które | ||
mog± byæ nazwami zmiennych; <math>x \in \mathbf{Var}</math>. | |||
Wreszcie, niech <math>\mathbf{Exp}</math> oznacza zbiór | Wreszcie, niech <math>\mathbf{Exp}</math> oznacza zbiór wyra¿eñ; | ||
<math>e \in \mathbf{Exp}</math>. | <math>e \in \mathbf{Exp}</math>. | ||
Dla | Dla u³atwienia zapisywania regu³ zak³adamy, ze sta³e | ||
liczbowe | liczbowe s± wyra¿eniami, czyli <math>\mathbf{Num} \subseteq \mathbf{Exp}</math>. | ||
Bêdziemy potrzebowaæ zbioru ''stanów'', opisuj±cych warto¶ci | |||
przypisane zmiennym. | przypisane zmiennym. | ||
Najprostszym | Najprostszym rozwi±zaniem jest przyj±c, ¿e stan to funkcja | ||
z <math>\mathbf{Var}</math> do <math>\mathbf{Num}</math>. | z <math>\mathbf{Var}</math> do <math>\mathbf{Num}</math>. | ||
Oznaczmy przez <math>\mathbf{State}</math> zbiór wszystkich takich funkcji; | Oznaczmy przez <math>\mathbf{State}</math> zbiór wszystkich takich funkcji; | ||
stany oznaczac | stany oznaczac bêdziemy przez <math>s, s_1, s', \ldots \in \mathbf{State}</math>. | ||
W naszej semantyce | W naszej semantyce bêdziemy potrzebowac tranzycji dwóch postaci. | ||
Po pierwsze, tranzycje postaci | Po pierwsze, tranzycje postaci | ||
Linia 67: | Linia 67: | ||
</math> | </math> | ||
oznaczaj±ce ma³y krok w trakcie obliczania wyra¿enia <math>e</math> | |||
w stanie <math>s</math>, w wyniku którego <math>e</math> | w stanie <math>s</math>, w wyniku którego <math>e</math> wyewoluowa³o do | ||
<math>e'</math>. Stan nie ulega zmiania podczas obliczania | <math>e'</math>. Stan nie ulega zmiania podczas obliczania wyra¿enia | ||
(nie ma tzw. ''efektów ubocznych''), | (nie ma tzw. ''efektów ubocznych''), | ||
wiêc to samo <math>s</math> figuruje po lewej i prawej stronie strza³ki. | |||
Po drugie, tranzycje postaci | Po drugie, tranzycje postaci | ||
Linia 78: | Linia 78: | ||
</math> | </math> | ||
bêd± oznaczaczaæ, ¿e wyra¿enie <math>e</math> jest ju¿ policzone, | |||
a jego | a jego warto¶ci± jest <math>n</math>. | ||
Zatem przyjmijmy, | Zatem przyjmijmy, ¿e zbiór konfiguracji to | ||
<math> | <math> | ||
Linia 87: | Linia 87: | ||
</math> | </math> | ||
a konfiguracje | a konfiguracje koñcowe to <math>\mathbf{Num}</math>. | ||
{{ | {{ | ||
uwaga||uwaga1| | uwaga||uwaga1| | ||
Tak | Tak naprawdê to druga postaæ tranzycji nie jest | ||
niezbêdna, gdy¿ mogliby¶my umówiæ siê, ¿e konfiguracje koñcowe | |||
to <math>\mathbf{Num} \times \mathbf{State}</math>. | to <math>\mathbf{Num} \times \mathbf{State}</math>. | ||
}} | }} | ||
Najprostsze | Najprostsze s± tranzycje prowadz±ce do konfiguracji koñcowej: | ||
<math> | <math> | ||
Linia 102: | Linia 102: | ||
</math> | </math> | ||
Symbol <math>n</math> po lewej stronie to | Symbol <math>n</math> po lewej stronie to wyra¿enie sk³adaj±ce siê | ||
ze | ze sta³ej liczbowej, podczas gdy <math>n</math> po prawej stronie reprezentuje liczbê | ||
bêd±c± warto¶ci± wyra¿enia. | |||
Zmienna oblicza | Zmienna oblicza siê do swojej warto¶ci w bie¿±cym stanie: | ||
<math> | <math> | ||
Linia 112: | Linia 112: | ||
</math> | </math> | ||
Teraz zajmiemy | Teraz zajmiemy siê dodawaniem <math>e_1 + e_2</math>. Poniewa¿ semantyka jest w stylu ma³ych | ||
kroków, musimy | kroków, musimy zdecydowaæ siê czy najpierw obliczyæ pierwszy (lewy) sk³adnik | ||
<math>e_1</math> czy drugi? | <math>e_1</math> czy drugi? | ||
Je¶li wybierzemy lewy (strategia ''lewostronna''), otrzymamy regu³ê: | |||
<math> | <math> | ||
Linia 123: | Linia 123: | ||
</math> | </math> | ||
Regu³y tej postaci bêdziemy zapisywaæ tak: | |||
<math> | <math> | ||
Linia 130: | Linia 130: | ||
</math> | </math> | ||
Czyli | Czyli ma³y krok w <math>e_1</math> stanowi te¿ ma³y krok w <math>e_1 + e_2</math>. | ||
Po | Po zakoñczeniu obliczania <math>e_1</math> przechodzimy do <math>e_2</math>: | ||
<math> | <math> | ||
Linia 138: | Linia 138: | ||
</math> | </math> | ||
A na | A na koñcu dodajemy: | ||
<math> | <math> | ||
Linia 144: | Linia 144: | ||
</math> | </math> | ||
Zwróæmy tutaj uwagê na pewn± subtelno¶æ, dotycz±c± dwóch wyst±pieñ | |||
symbolu <math>+</math>: pierwsze | symbolu <math>+</math>: pierwsze wyst±pienie oznacza jedn± z konstrukcji sk³adniowych | ||
jêzyka, a drugie oznacza operacjê dodawania w zbiorze <math>\mathbf{Num}</math>. | |||
Pozwalamy sobie na | Pozwalamy sobie na tak± kolizjê oznaczeñ, gdy¿ nie powinna ona | ||
prowadziæ do niejednoznaczno¶ci. Pamiêtajmy, ¿e sk³adnia jêzyka jest | |||
sk³adni± abstrakcyjn±, wiêc zamiast <math>e_1 + e_2</math> mogliby¶my równie | |||
dobrze | dobrze pisaæ np. <math>{\mathrm{add}}(e_1, e_2)</math> a wtedy regu³a | ||
wygl±da³aby tak: | |||
<math> | <math> | ||
Linia 157: | Linia 157: | ||
</math> | </math> | ||
Inn± mo¿liw± strategi± obliczania <math>e_1 + e_2</math> jest strategia | |||
''prawostronna'', | ''prawostronna'', któr± otrzymujemy zastêpuj±c pierwsze dwie z trzech | ||
powy¿szych regu³ przez: | |||
<math> | <math> | ||
Linia 169: | Linia 169: | ||
</math> | </math> | ||
Ponadto, | Ponadto, je¶li przyjmiemy regu³ê pierwsz± (dla <math>e_1</math>), trzeci± | ||
i | i czwart± (dla <math>e_2</math>), otrzymamy strategiê | ||
'' | ''równoleg³±'', polegaj±c± na obliczaniu jednocze¶nie <math>e_1</math> i | ||
<math>e_2</math>: | <math>e_2</math>: | ||
Linia 184: | Linia 184: | ||
</math> | </math> | ||
Bardziej precyzyjnie | Bardziej precyzyjnie mówi±c, ma³e kroki obliczaj±ce | ||
obydwa | obydwa podwyra¿enia przeplataj± siê, i to w dowolny sposób. | ||
Ta | Ta dowolno¶æ prowadzi do ''niedeterminizmu'', czyli do sytuacji, gdy | ||
kolejna ( | kolejna (nastêpna) konfiguracja nie jest wyznaczona jednoznacznie. | ||
Jest tak, | Jest tak, gdy¿ mo¿emy mieæ do wyboru dwie ró¿ne tranzycje | ||
<math> | <math> | ||
Linia 196: | Linia 196: | ||
</math> | </math> | ||
Zauwa¿my natomiast, ¿e kolejno¶æ przeplatania siê ma³ych kroków obliczaj±cych | |||
<math>e_1</math> i <math>e_2</math> nie | <math>e_1</math> i <math>e_2</math> nie wp³ywa w tym przypadku na koñcow± warto¶æ | ||
ca³ego wyra¿enia. | |||
Na koniec | Na koniec regu³y dla wyra¿enia warunkowego. | ||
<math> | <math> | ||
Linia 221: | Linia 221: | ||
{{cwiczenie|2|cw2| | {{cwiczenie|2|cw2| | ||
Rozszerzmy | Rozszerzmy jêzyk wyra¿eñ z poprzedniego zadania o jedn± konstrukcjê | ||
<math> | <math> | ||
Linia 229: | Linia 229: | ||
</math> | </math> | ||
Wyra¿enie <math>\mathbf{let}\, x = e_1 \,\mathbf{in}\, e_2</math> zawiera w sobie deklaracjê | |||
<math>x = e_1</math>, która stanowi mechanizm | <math>x = e_1</math>, która stanowi mechanizm wi±zania | ||
identyfikatorów w naszym | identyfikatorów w naszym jêzyku. | ||
Deklaracja <math>x = e_1</math> wprowadza | Deklaracja <math>x = e_1</math> wprowadza now± zmienn± <math>x</math> | ||
oraz przypisuje jej | oraz przypisuje jej warto¶æ. | ||
Warto¶æ wyra¿enia <math>\mathbf{let}\, x = e_1 \,\mathbf{in}\, e_2</math> obliczamy nastêpuj±co: | |||
najpierw oblicza | najpierw oblicza siê warto¶æ <math>e_1</math>, podstawia j± na zmienna | ||
<math>x</math>, a | <math>x</math>, a nastêpnie oblicza wyra¿enie <math>e_2</math>. | ||
Zakresem zmiennej <math>x</math> jest | Zakresem zmiennej <math>x</math> jest wyra¿enie <math>e_2</math>, czyli | ||
wewn±trz <math>e_2</math> mo¿na odwo³ywaæ siê (wielokrotnie) do zmiennej <math>x</math>; | |||
Ogólniej, | Ogólniej, odwo³ania do zmiennej w wyra¿eniu odnosz± siê do ''najbli¿szej'' | ||
(najbardziej | (najbardziej zagnie¿dzonej) deklaracji tej zmiennej. | ||
Taki mechanizm | Taki mechanizm wi±zania identyfikatorów nazywamy ''wi±zaniem | ||
statycznym''. | statycznym''. | ||
Przyjmujemy | Przyjmujemy zwyk³e (statyczne) regu³y przes³aniania zmiennych, np. | ||
je¶li w <math>e_2</math> wystêpuje podwyra¿enie <math>\mathbf{let}\, x = e \,\mathbf{in}\, e'</math> to | |||
deklaracja <math>x = e</math> ''przes³ania'' deklaracjê <math>x = e_1</math> | |||
w wyra¿eniu <math>e'</math>. | |||
Zak³adamy, ¿e na pocz±tku warto¶ci wszystkich zmiennych s± | |||
'' | ''nieokre¶lone'', czyli zmienne s± niezainicjowane, a odwo³anie do | ||
niezainicjowanej zmiennej jest | niezainicjowanej zmiennej jest uwa¿ane za niepoprawne. | ||
}} | }} | ||
Linia 268: | Linia 268: | ||
<math> | <math> | ||
\mathbf{let}\, z = 5 \,\mathbf{in}\, x+z | \mathbf{let}\, z = 5 \,\mathbf{in}\, x+z | ||
\quad \quad \mapsto \quad \quad \mbox{brak wyniku; | \quad \quad \mapsto \quad \quad \mbox{brak wyniku; odwo³anie do niezainicjowanej | ||
zmiennej}\, x | zmiennej}\, x | ||
</math> | </math> | ||
Linia 284: | Linia 284: | ||
Podobnie jak poprzednio, | Podobnie jak poprzednio, | ||
stan powinien | stan powinien opisywaæ warto¶ci przypisane zmiennym. | ||
Tym razem jednak | Tym razem jednak | ||
uwzglêdnimy niezainicjowane zmienne, czyli zmienne bez ¿adnej warto¶ci. | |||
Przyjmijmy zatem, | Przyjmijmy zatem, ¿e stan to skoñczona funkcja czê¶ciowa z <math>\mathbf{Var}</math> do <math>\mathbf{Num}</math>. | ||
Oznaczmy symbolem <math>\mathbf{State}</math> zbiór wszystkich takich funkcji: | Oznaczmy symbolem <math>\mathbf{State}</math> zbiór wszystkich takich funkcji: | ||
<math> | <math> | ||
\mathbf{State} = \mathbf{Var} \to_{\mathrm{fin}} \mathbf{Num} | \mathbf{State} = \mathbf{Var} \to_{\mathrm{fin}} \mathbf{Num} | ||
</math>. | </math>. | ||
Naturalnym stanem | Naturalnym stanem pocz±tkowym jest stan ''pusty'', tzn. | ||
pusta funkcja | pusta funkcja czê¶ciowa, który bêdziemy oznaczaæ symbolem <math>\emptyset</math>. | ||
Warto¶æ wyra¿enia <math>e</math> w stanie pocz±tkowym wynosi <math>n</math> | |||
o ile zachodzi: | o ile zachodzi: | ||
Linia 301: | Linia 301: | ||
</math> | </math> | ||
Bêdziemy potrzebowac tranzycji dwóch postaci, podobnie jak poprzednio, | |||
ale pierwsza | ale pierwsza postaæ bêdzie trochê ogólniejsza: | ||
<math> | <math> | ||
Linia 308: | Linia 308: | ||
</math> | </math> | ||
Tranzycja ta oznacza | Tranzycja ta oznacza ma³y krok w trakcie obliczania wyra¿enia <math>e</math> | ||
w stanie <math>s</math>, w wyniku którego <math>e</math> | w stanie <math>s</math>, w wyniku którego <math>e</math> wyewoluowa³o do | ||
<math>e'</math> a nowym stanem jest <math>s'</math>. | <math>e'</math> a nowym stanem jest <math>s'</math>. | ||
Stan | Stan mo¿e siê teraz zmieniæ na skutek deklaracji zmiennych. | ||
Spróbujmy rozszerzyc | Spróbujmy rozszerzyc semantykê z poprzedniego zadania. | ||
Poniewa¿ stan jest funkcj± czê¶ciow±, musimy zmieniæ niektóre regu³y, np. | |||
<math> | <math> | ||
x, s \,\Longrightarrow\, n, s \quad \mbox{ o ile } s(x) \mbox{ jest | x, s \,\Longrightarrow\, n, s \quad \mbox{ o ile } s(x) \mbox{ jest okre¶lone i } s(x) = n | ||
</math> | </math> | ||
Nastêpnie dodajemy regu³y dla wyra¿enia | |||
<math>\mathbf{let}\, x = e_1 \,\mathbf{in}\, e_2</math>. | <math>\mathbf{let}\, x = e_1 \,\mathbf{in}\, e_2</math>. | ||
Gdy <math>e_1</math> jest | Gdy <math>e_1</math> jest ju¿ obliczne, wyatarczy regu³a: | ||
<math> | <math> | ||
Linia 329: | Linia 329: | ||
Notacja <math>s[x \mapsto n]</math> oznacza stan <math>s</math>, który zmodyfikowano | Notacja <math>s[x \mapsto n]</math> oznacza stan <math>s</math>, który zmodyfikowano | ||
przypisuj±c zmiennej <math>x</math> warto¶æ <math>n</math>, | |||
niezale¿nie od tego, czy <math>s(x)</math> by³o okre¶lone, czy nie, | |||
i | i pozostawiaj±c niezmienione warto¶ci dla pozosta³ych zmiennych. | ||
Formanie | Formanie | ||
Linia 342: | Linia 342: | ||
</math> | </math> | ||
W | W szczególno¶ci, | ||
dla <math>y \neq x</math>, <math>s[x \mapsto n](y)</math> jest | dla <math>y \neq x</math>, <math>s[x \mapsto n](y)</math> jest okre¶lone wtedy i tylko | ||
wtedy, gdy <math>s(y)</math> jest | wtedy, gdy <math>s(y)</math> jest okre¶lone. | ||
Natomiast aby obliczyc <math>e_1</math> potrzebujemy | Natomiast aby obliczyc <math>e_1</math> potrzebujemy regu³y: | ||
<math> | <math> | ||
Linia 353: | Linia 353: | ||
</math> | </math> | ||
Zwróæmy uwagê, ¿e stan <math>s'</math> mo¿e byæ ró¿ny od <math>s</math>, | |||
np. dlatego, | np. dlatego, ¿e wewn±trz <math>e_1</math> znajduje siê podwyra¿enie | ||
<math>\mathbf{let}\, y = \ldots</math>. | <math>\mathbf{let}\, y = \ldots</math>. | ||
'''Pytanie:''' czy taka semantyka jest poprawna? | '''Pytanie:''' czy taka semantyka jest poprawna? | ||
Niestety nie, | Niestety nie, gdy¿ nie uwzglêdniamy ograniczonego zasiêgu zmiennej. | ||
Rzuæmy okiem na przyk³ad: | |||
<math> | <math> | ||
Linia 366: | Linia 366: | ||
</math> | </math> | ||
Wed³ug naszych intencji to wyra¿enie nie ma warto¶ci, gdy¿ ostatnie | |||
odwo³anie do <math>z</math> jest b³êdne. | |||
Natomiast | Natomiast wed³ug powy¿szych regu³ mamy | ||
<math> | <math> | ||
Linia 378: | Linia 378: | ||
</math> | </math> | ||
Nasz | Nasz b³±d polega na tym, ¿e po zakoñczeniu obliczania podwyra¿enia | ||
<math>\mathbf{let}\, z = 4 \,\mathbf{in}\, z+z+z</math> ''zapominamy'' | <math>\mathbf{let}\, z = 4 \,\mathbf{in}\, z+z+z</math> ''zapominamy'' przywróciæ zmiennej <math>z</math> | ||
poprzedni± warto¶æ (a w³a¶ciwie brak warto¶ci w przyk³adzie powy¿ej). | |||
Przedyskutujmy kilka wariantów. | Przedyskutujmy kilka wariantów. | ||
Linia 388: | Linia 388: | ||
<br> | <br> | ||
Wygodne i eleganckie | Wygodne i eleganckie rozwi±zanie tego problemu jest mo¿liwe, je¶li | ||
rozszerzymy | rozszerzymy sk³adniê naszego jêzyka. | ||
Intuicyjnie, | Intuicyjnie, regu³a | ||
<math> | <math> | ||
Linia 396: | Linia 396: | ||
</math> | </math> | ||
powinna | powinna zostaæ zast±piona przez | ||
<math> | <math> | ||
\mathbf{let}\, x = n \,\mathbf{in}\, e_2, s \,\Longrightarrow\, e_2 \,\mathbf{then}\, \mbox{,, | \mathbf{let}\, x = n \,\mathbf{in}\, e_2, s \,\Longrightarrow\, e_2 \,\mathbf{then}\, \mbox{,,przywróæ warto¶æ zmiennej x''}, s[x \mapsto n]. | ||
</math> | </math> | ||
czyli potrzebujemy konstrukcji | czyli potrzebujemy konstrukcji sk³adniowej, która polega na obliczeniu | ||
wyra¿enia | |||
<math>e_2</math> a | <math>e_2</math> a nastêpnie na przypisaniu zmiennej <math>x</math> danej warto¶ci. | ||
Rozszerzmy zatem | Rozszerzmy zatem sk³adniê nastêpujaco: | ||
<math> | <math> | ||
Linia 413: | Linia 413: | ||
</math> | </math> | ||
Wyra¿enie <math>e \,\mathbf{then}\, x:= n</math> jest w pewnym sensie dualne | |||
do <math>\mathbf{let}\, x = n \,\mathbf{in}\, e</math>, | do <math>\mathbf{let}\, x = n \,\mathbf{in}\, e</math>, gdy¿ jedyna (choc niew±tpliwie istotna) ró¿nica | ||
miêdzy nimi to kolejno¶æ obliczenia <math>e</math> i przypisania warto¶ci | |||
na | na zmienn± <math>x</math>. | ||
Oto nowa | Oto nowa regu³a | ||
<math> | <math> | ||
Linia 424: | Linia 424: | ||
</math> | </math> | ||
Pewna | Pewna trudno¶æ pojawia siê w sytuacji, gdy <math>s(x)</math> jest | ||
nieokre¶lone, czyli gdy zmienna <math>x</math> jest niezainicjowana -- regu³a | |||
powy¿sza nie obejmuje wogóle takiej sytuacji. | |||
Najprostszym sposobem | Najprostszym sposobem rozwi±zania tej trudno¶ci jest rozszerzenie | ||
konstrukcji <math>e \,\mathbf{then}\, x := n</math>: | konstrukcji <math>e \,\mathbf{then}\, x := n</math>: | ||
Linia 437: | Linia 437: | ||
</math> | </math> | ||
gdzie symbol <math>\bot</math> oznacza brak | gdzie symbol <math>\bot</math> oznacza brak warto¶ci. | ||
Dodajemy | Dodajemy równie¿ regu³ê: | ||
<math> | <math> | ||
\mathbf{let}\, x = n \,\mathbf{in}\, e_2, s \,\Longrightarrow\, e_2 \,\mathbf{then}\, x := \bot, s[x \mapsto n] \quad | \mathbf{let}\, x = n \,\mathbf{in}\, e_2, s \,\Longrightarrow\, e_2 \,\mathbf{then}\, x := \bot, s[x \mapsto n] \quad | ||
\mbox{ o ile } s(x) \, \mbox{ jest | \mbox{ o ile } s(x) \, \mbox{ jest nieokre¶lone}. | ||
</math> | </math> | ||
Rozwi±zanie to jest odrobinê nieeleganckie, gdy¿ prawie identyczne regu³y | |||
musimy | musimy napisaæ dwukrotnie. | ||
Widaæ to np. w poni¿szych regu³ach, ''scalaj±cych'' semantykê dla <math>e \,\mathbf{then}\, x := n</math> | |||
z | z semantyk± pozosta³ych wyra¿eñ: | ||
<math> | <math> | ||
Linia 461: | Linia 461: | ||
<math> | <math> | ||
n' \,\mathbf{then}\, x := \bot, s \,\Longrightarrow\, n', s' \quad \mbox{ o ile } s(x) | n' \,\mathbf{then}\, x := \bot, s \,\Longrightarrow\, n', s' \quad \mbox{ o ile } s(x) | ||
\mbox{ jest | \mbox{ jest okre¶lone i } s' = s \setminus \{ (x, s(x)) \} | ||
</math> | </math> | ||
Linia 469: | Linia 469: | ||
<br> | <br> | ||
Zanim przejdziemy do kolejnego wariantu, zastanówmy | Zanim przejdziemy do kolejnego wariantu, zastanówmy siê czy | ||
istnieje inny sposób | istnieje inny sposób rozwi±zania trudno¶ci zwi±zanej z <math>n = | ||
\bot</math>, który | \bot</math>, który pozwala³by unikn±æ wprowadzania dodatkowej konstrukcji | ||
<math>e \,\mathbf{then}\, x := \bot</math>. | <math>e \,\mathbf{then}\, x := \bot</math>. | ||
Pomys³ mo¿e polegaæ na rozszerzeniu | |||
zbioru <math>\mathbf{Num}</math> o dodatkowy element <math>\bot</math>: | zbioru <math>\mathbf{Num}</math> o dodatkowy element <math>\bot</math>: | ||
Linia 480: | Linia 480: | ||
</math> | </math> | ||
Wtedy nie musimy | Wtedy nie musimy pisaæ dwóch bardzo podobnych wariantów regu³. | ||
Dodatkowo, w tym | Dodatkowo, w tym rozwi±zaniu warto poczyniæ umowê, ¿e | ||
<math>s(x) = \bot</math> reprezentuje brak | <math>s(x) = \bot</math> reprezentuje brak warto¶ci zmiennej <math>x</math>. | ||
Wtedy stany | Wtedy stany s± funkcjami ca³kowitymi z <math>\mathbf{Var}</math> w <math>\mathbf{Num}</math> | ||
przyjmuj±cymi warto¶æ ró¿n± od <math>\bot</math> tylko dla skoñczenie | |||
wielu elementów. | wielu elementów. | ||
Pewnym mankamentem jest to, | Pewnym mankamentem jest to, ¿e teraz | ||
<math>n = \bot</math> | <math>n = \bot</math> mo¿e pojawiaæ sie w wyra¿eniach podobnie jak sta³e. | ||
Tym niemniej nie musimy | Tym niemniej nie musimy adaptowaæ regu³ dla sta³ych tak, aby radzi³y | ||
one sobie z <math>n = \bot</math>, | one sobie z <math>n = \bot</math>, poniewa¿ wyra¿enia zawieraj±ce | ||
<math>\bot</math> | <math>\bot</math> mo¿emy równie¿ uwa¿aæ za roszerzenie sk³adni. | ||
Je¶li jednak dopu¶cimy symbol <math>\bot</math> w wyra¿eniach, to mo¿emy | |||
elegancko | elegancko wybrn±æ z sytuacji, rozszerzaj±c operacje arytmetyczne | ||
na zbiór <math>\mathbf{Num} \cup \{ \bot \}</math> tak, aby | na zbiór <math>\mathbf{Num} \cup \{ \bot \}</math> tak, aby zachowywa³y one | ||
nieokre¶lono¶æ: | |||
<math> | <math> | ||
Linia 501: | Linia 501: | ||
</math> | </math> | ||
Trzeba jednak w takim razie | Trzeba jednak w takim razie zadbaæ o to, aby wyra¿enie <math>\mathbf{let}\, x = e_1 | ||
\,\mathbf{in}\, e_2</math> | \,\mathbf{in}\, e_2</math> oblicza³o siê normalnie tylko wtedy, gdy warto¶æ | ||
wyra¿enia <math>e_1</math> jest ró¿na od <math>\bot</math>. | |||
Linia 510: | Linia 510: | ||
<br> | <br> | ||
Zrewidujmy teraz podstawowe | Zrewidujmy teraz podstawowe za³o¿enia, które dotychczas poczynili¶my. | ||
Jednym z nich | Jednym z nich by³o przyjêcie ogólnej postaci tranzycji: | ||
<math> | <math> | ||
Linia 517: | Linia 517: | ||
</math> | </math> | ||
pozwalaj±cej na zmianê stanu podczas obliczania wyra¿enia. | |||
Czy faktycznie | Czy faktycznie by³ to dobry pomys³? Czy mogliby¶my poradziæ sobie | ||
przy pomocy tranzycji postaci | przy pomocy tranzycji postaci | ||
Linia 525: | Linia 525: | ||
</math> | </math> | ||
Spróbujmy! Oto nowa wersja jednej z | Spróbujmy! Oto nowa wersja jednej z regu³ dla <math>\mathbf{let}\, x = e_1 \,\mathbf{in}\, e_2</math> | ||
dotycz±ca kroku wewn±trz <math>e_1</math>: | |||
<math> | <math> | ||
Linia 533: | Linia 533: | ||
</math> | </math> | ||
Dotychczas nie ma problemu: | Dotychczas nie ma problemu: podwyra¿enie <math>e_1</math> jest | ||
prawid³owo obliczane w stanie <math>s</math>. Trudno¶æ pojawi siê, gdy | |||
zakoñczymy obliczanie <math>e_1</math> i przejdziemy do <math>e_2</math>. | |||
Oto | Oto mo¿liwa regu³a: | ||
<math> | <math> | ||
Linia 543: | Linia 543: | ||
</math> | </math> | ||
Okazuje | Okazuje siê, ¿e wszystko jest w porz±dku. Wyra¿enie <math>e</math> | ||
obliczamy w | obliczamy w prawid³owym stanie, tzn. z warto¶ci± <math>n</math> | ||
przypisan± zmiennej <math>x</math>. | |||
Ma³y krok w <math>e</math> daje przyczynek do ma³ego kroku w ca³ym | |||
wyra¿eniu, a przy tym stan pozostaje niezmieniony. | |||
Przy tym wogóle nie potrzebujemy | Przy tym wogóle nie potrzebujemy przywracaæ poprzedniej warto¶ci | ||
zmiennej <math>x</math>, | zmiennej <math>x</math>, poniewa¿ <math>x</math> zyskuje now± warto¶æ | ||
''tylko'' na potrzeby obliczania | ''tylko'' na potrzeby obliczania podwyra¿enia <math>e</math>! | ||
Mo¿na na to równie¿ spojrzeæ inaczej: informacja o nowej warto¶ci | |||
<math>n</math> dla zmiennej <math>x</math> nie jest jawnie dodawana do stanu | <math>n</math> dla zmiennej <math>x</math> nie jest jawnie dodawana do stanu | ||
<math>s</math>, ale jest przechowywana w | <math>s</math>, ale jest przechowywana w sk³adni wyra¿enia | ||
<math>\mathbf{let}\, x = n \,\mathbf{in}\, \ldots</math> jako deklaracja <math>x = n</math>. | <math>\mathbf{let}\, x = n \,\mathbf{in}\, \ldots</math> jako deklaracja <math>x = n</math>. | ||
Na | Na koñcu musimy oczywi¶cie pozbyæ siê tej deklaracji za pomoc± | ||
nastêpuj±cej tranzycji: | |||
<math> | <math> | ||
Linia 562: | Linia 562: | ||
</math> | </math> | ||
Podsumujmy. Okazuje | Podsumujmy. Okazuje siê, ¿e rozwi±zanie nie by³o wcale ³atwe, | ||
nawet dla tak | nawet dla tak pro¶ciutkiego jêzyka. W przysz³o¶ci przekonamy siê, | ||
¿e ³atwiej jest poradziæ sobie z zagadnieniem wi±zania identyfikatorów | |||
w semantyce naturalnej ( | w semantyce naturalnej (du¿e kroki). | ||
W wariancie 1 i 2 | W wariancie 1 i 2 wprowadzili¶my do jêzyka dodatkowe elementy, tak, | ||
by | by ³atwiej by³o pisaæ regu³y. W przysz³o¶ci bêdziemy czasem stosowaæ | ||
takie | takie podej¶cie. | ||
Niekiedy jednak rozszerzanie | Niekiedy jednak rozszerzanie jêzyka bêdzie zabronione. | ||
</div></div> | </div></div> | ||
Linia 578: | Linia 578: | ||
{{cwiczenie|1|cw1.dom| | |||
Zapisz wariant 2 semantyki z poprzedniego zadania. | Zapisz wariant 2 semantyki z poprzedniego zadania. | ||
}} | |||
{{cwiczenie|2|cw2.dom| | |||
Dotychczas | Dotychczas wyst±pienie b³êdu podczas obliczania wyra¿enia, | ||
np. | np. odwo³anie do niezainicjowanej zmiennej, powodowa³o, ¿e | ||
wyra¿enie nie posiada³o warto¶ci (nie by³o ci±gu tranzycji | |||
prowadz±cych do konfiguracji koñcowej). Zmodyfikuj któr±¶ z semantyk | |||
z poprzednich | z poprzednich zadañ tak, aby b³±d by³ komunikowany | ||
jako jedna z konfiguracji | jako jedna z konfiguracji koñcowych. To znaczy: je¶li obliczenie | ||
wyra¿enia <math>e</math> w stanie <math>s</math> jest niemo¿liwe bo wyst±pi³ | |||
b³±d, to | |||
<math> | <math> | ||
e, s \,\Longrightarrow^{*}\, \mathtt{Blad} | e, s \,\Longrightarrow^{*}\, \mathtt{Blad}. | ||
</math> | </math> | ||
}} | |||
{{cwiczenie|3|cw3.dom| | |||
Rozwa¿ rozszerzenie jêzyka wyra¿eñ o wyra¿enia boolowskie: | |||
<math> | <math> | ||
Linia 630: | Linia 632: | ||
</math> | </math> | ||
Zaproponuj | Zaproponuj semantykê ma³ych kroków dla tego jêzyka. | ||
Rozwa¿ ró¿ne strategie obliczania wyra¿eñ boolowskich, oraz podej¶cie leniwe. | |||
Na | Na przyk³ad w strategii lewostronnej dla <math>b_1 \land b_2</math>, | ||
gdy <math>b_1</math> | gdy <math>b_1</math> zosta³o obliczone do <math>\mathbf{false}</math>, w podej¶ciu leniwym nie ma wogóle potrzeby | ||
obliczania <math>b_2</math>. | obliczania <math>b_2</math>. | ||
}} |
Wersja z 07:57, 9 sie 2006
Zawarto¶æ
Tematem tych zajêæ jest semantyka operacyjna wyra¿eñ (ma³e kroki).
Semantyka operacyjna wyra¿eñ
Ćwiczenie 1
Rozwa¿my bardzo prosty jêzyk wyra¿eñ, którego sk³adnia opisana jest nastêpuj±c± gramatyk±:
Wynikiem wyra¿enienia warunkowego jest warto¶æ wyra¿enia , o ile wyra¿enie oblicza siê do warto¶ci ró¿nej od zera; w przeciwnym przypadku wynikiem jest warto¶æ wyra¿enia .
Zaproponuj semantykê operacyjn± (ma³e kroki) dla tego jêzyka.
Rozwiązanie
Ćwiczenie 2
Rozszerzmy jêzyk wyra¿eñ z poprzedniego zadania o jedn± konstrukcjê
Wyra¿enie zawiera w sobie deklaracjê , która stanowi mechanizm wi±zania identyfikatorów w naszym jêzyku. Deklaracja wprowadza now± zmienn± oraz przypisuje jej warto¶æ. Warto¶æ wyra¿enia obliczamy nastêpuj±co: najpierw oblicza siê warto¶æ , podstawia j± na zmienna , a nastêpnie oblicza wyra¿enie . Zakresem zmiennej jest wyra¿enie , czyli wewn±trz mo¿na odwo³ywaæ siê (wielokrotnie) do zmiennej ; Ogólniej, odwo³ania do zmiennej w wyra¿eniu odnosz± siê do najbli¿szej (najbardziej zagnie¿dzonej) deklaracji tej zmiennej. Taki mechanizm wi±zania identyfikatorów nazywamy wi±zaniem statycznym. Przyjmujemy zwyk³e (statyczne) regu³y przes³aniania zmiennych, np. je¶li w wystêpuje podwyra¿enie to deklaracja przes³ania deklaracjê w wyra¿eniu .
Zak³adamy, ¿e na pocz±tku warto¶ci wszystkich zmiennych s± nieokre¶lone, czyli zmienne s± niezainicjowane, a odwo³anie do niezainicjowanej zmiennej jest uwa¿ane za niepoprawne.
Przykład
Parser nie mógł rozpoznać (błąd składni): {\displaystyle \mathbf{let}\, z = 5 \,\mathbf{in}\, x+z \quad \quad \mapsto \quad \quad \mbox{brak wyniku; odwo³anie do niezainicjowanej zmiennej}\, x }
Rozwiązanie
Zadania domowe
Ćwiczenie 1
Zapisz wariant 2 semantyki z poprzedniego zadania.
Ćwiczenie 2
Dotychczas wyst±pienie b³êdu podczas obliczania wyra¿enia, np. odwo³anie do niezainicjowanej zmiennej, powodowa³o, ¿e wyra¿enie nie posiada³o warto¶ci (nie by³o ci±gu tranzycji prowadz±cych do konfiguracji koñcowej). Zmodyfikuj któr±¶ z semantyk z poprzednich zadañ tak, aby b³±d by³ komunikowany jako jedna z konfiguracji koñcowych. To znaczy: je¶li obliczenie wyra¿enia w stanie jest niemo¿liwe bo wyst±pi³ b³±d, to
Ćwiczenie 3
Rozwa¿ rozszerzenie jêzyka wyra¿eñ o wyra¿enia boolowskie:
Zaproponuj semantykê ma³ych kroków dla tego jêzyka. Rozwa¿ ró¿ne strategie obliczania wyra¿eñ boolowskich, oraz podej¶cie leniwe. Na przyk³ad w strategii lewostronnej dla , gdy zosta³o obliczone do , w podej¶ciu leniwym nie ma wogóle potrzeby obliczania .