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

Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania
m Zastępowanie tekstu – „.↵</math>” na „</math>”
 
(Nie pokazano 3 pośrednich wersji utworzonych przez tego samego użytkownika)
Linia 43: Linia 43:
\mathbf{Store} = \mathbf{Loc} \to_{\mathrm{fin}} \mathbf{Num}  
\mathbf{Store} = \mathbf{Loc} \to_{\mathrm{fin}} \mathbf{Num}  
\quad \quad \quad
\quad \quad \quad
\mathbf{Env}= \mathbf{Var} \to_{\mathrm{fin}} (\mathbf{Loc} \cup \mathbf{Proc}).
\mathbf{Env}= \mathbf{Var} \to_{\mathrm{fin}} (\mathbf{Loc} \cup \mathbf{Proc})</math>
</math>


Nowym elementem jest zbiór <math>\mathbf{Proc}</math>, potrzebny nam do przechowywania informacji o procedurach.  
Nowym elementem jest zbiór <math>\mathbf{Proc}</math>, potrzebny nam do przechowywania informacji o procedurach.  
Linia 93: Linia 92:
E \,\vdash\, \mathbf{proc}\, x_1(x_2);\, I, s \,\longrightarrow\, (E', s)
E \,\vdash\, \mathbf{proc}\, x_1(x_2);\, I, s \,\longrightarrow\, (E', s)
\quad \mbox{ gdzie }
\quad \mbox{ gdzie }
E' = E[x_1 \mapsto \langle x_2, I, E \rangle].
E' = E[x_1 \mapsto \langle x_2, I, E \rangle]</math>
</math>


Zauważmy, że deklaracja procedury nie zmienia stanu, tylko środowisko, w odróżnieniu od deklaracji zmiennej.
Zauważmy, że deklaracja procedury nie zmienia stanu, tylko środowisko, w odróżnieniu od deklaracji zmiennej.
Linia 143: Linia 141:
\quad \mbox{ o ile }
\quad \mbox{ o ile }
E(x_1) = \langle x, I, E' \rangle \in \mathbf{Proc} \mbox{ i }
E(x_1) = \langle x, I, E' \rangle \in \mathbf{Proc} \mbox{ i }
E(x_2) = l \in \mathbf{Loc}.
E(x_2) = l \in \mathbf{Loc}</math>
</math>


Czyli uruchamiane jest ciało <math>I</math> procedury, w środowisku <math>E'</math> z miejsca deklaracji tej procedury zmodyfikowanym o przypisanie <math>x \mapsto l</math> lokacji <math>l</math> do parametru formalnego <math>x</math> procedury.
Czyli uruchamiane jest ciało <math>I</math> procedury, w środowisku <math>E'</math> z miejsca deklaracji tej procedury zmodyfikowanym o przypisanie <math>x \mapsto l</math> lokacji <math>l</math> do parametru formalnego <math>x</math> procedury.
Linia 160: Linia 157:
\quad \mbox{ o ile }
\quad \mbox{ o ile }
E(x_1) = \langle x, I, E' \rangle \in \mathbf{Proc} \mbox{ i }
E(x_1) = \langle x, I, E' \rangle \in \mathbf{Proc} \mbox{ i }
E(x_2) = l \in \mathbf{Loc}.
E(x_2) = l \in \mathbf{Loc}</math>
</math>


Zauważmy, że przypisanie <math>x_1 \mapsto \langle x, I, E' \rangle</math> dodane  do <math>E'</math> wystarcza na tylko jedno wywołanie rekurencyjne (licząc w głąb).  
Zauważmy, że przypisanie <math>x_1 \mapsto \langle x, I, E' \rangle</math> dodane  do <math>E'</math> wystarcza na tylko jedno wywołanie rekurencyjne (licząc w głąb).  
Linia 179: Linia 175:
\quad \mbox{ o ile }
\quad \mbox{ o ile }
E(x_1) = \langle x, I, E' \rangle \in \mathbf{Proc} \mbox{ i }
E(x_1) = \langle x, I, E' \rangle \in \mathbf{Proc} \mbox{ i }
E(x_2) = l \in \mathbf{Loc}.
E(x_2) = l \in \mathbf{Loc}</math>
</math>


Czy obydwie semantyki są sobie równoważne?
Czy obydwie semantyki są sobie równoważne?
Linia 187: Linia 182:




  <math>\mathbf{begin}\,</math>
  <math>\mathbf{begin}\ </math>,
   <math>\mathbf{var}\,</math> y = 7;
   <math>\mathbf{var}\ </math>, y = 7;
   <math>\mathbf{proc}\,</math> x(x); x := x+1;
   <math>\mathbf{proc}\ </math>, x(x); x := x+1;
   
   
   <math>\mathbf{call}\,</math> x(y);
   <math>\mathbf{call}\ </math>, x(y);
  <math>\,\mathbf{end}</math>
  <math>\,\mathbf{end}</math>






  <math>\mathbf{begin}\,</math>
  <math>\mathbf{begin}\ </math>,
   <math>\mathbf{var}\,</math> y = 7;
   <math>\mathbf{var}\ </math>, y = 7;
   <math>\mathbf{proc}\,</math> x(x);
   <math>\mathbf{proc}\ </math>, x(x);
     <math>\mathbf{if}\,</math> y > 0 <math>\,\mathbf{then}\,</math> y := y-1; <math>\mathbf{call}\,</math> x(y) <math>\,\mathbf{else}\, \mathbf{skip}</math>;
     <math>\mathbf{if}\ </math>, y > 0 <math>\,\mathbf{then}\ </math>, y := y-1; <math>\mathbf{call}\ </math>, x(y) <math>\,\mathbf{else}\, \mathbf{skip}</math>;


   <math>\mathbf{call}\,</math> x(y);
   <math>\mathbf{call}\ </math>, x(y);
  <math>\,\mathbf{end}</math>
  <math>\,\mathbf{end}</math>


Linia 269: Linia 264:
E \,\vdash\, \mathbf{proc}\, x_1(x_2);\, I, s \,\longrightarrow\, (E', s, \emptyset)
E \,\vdash\, \mathbf{proc}\, x_1(x_2);\, I, s \,\longrightarrow\, (E', s, \emptyset)
\quad \mbox{ gdzie }
\quad \mbox{ gdzie }
E' = E[x_1 \mapsto \langle x_2, I, E \rangle].
E' = E[x_1 \mapsto \langle x_2, I, E \rangle]</math>
</math>


<math>
<math>
Linia 305: Linia 299:
}}
}}


  <math>\mathbf{begin}\,</math>
  <math>\mathbf{begin}\ </math>,
   <math>\mathbf{var}\,</math> x = 1;
   <math>\mathbf{var}\ </math>, x = 1;
   <math>\mathbf{proc}\,</math> p(y); y := y+x;
   <math>\mathbf{proc}\ </math>, p(y); y := y+x;
   
   
   <math>\mathbf{begin}\,</math>
   <math>\mathbf{begin}\ </math>,
     <math>\mathbf{var}\,</math> x = 10; <math>\mathbf{var}\,</math> z = 0;
     <math>\mathbf{var}\ </math>, x = 10; <math>\mathbf{var}\ </math>, z = 0;
   
   
     <math>\mathbf{call}\,</math> p(z);
     <math>\mathbf{call}\ </math>, p(z);
   <math>\,\mathbf{end}</math>
   <math>\,\mathbf{end}</math>
  <math>\,\mathbf{end}</math>
  <math>\,\mathbf{end}</math>
Linia 321: Linia 315:




  <math>\mathbf{begin}\,</math>
  <math>\mathbf{begin}\ </math>,
   <math>\mathbf{proc}\,</math> q(x); x := x+1;
   <math>\mathbf{proc}\ </math>, q(x); x := x+1;
   <math>\mathbf{proc}\,</math> p(y); <math>\mathbf{call}\,</math> q(y); <math>\mathbf{call}\,</math> q(y);
   <math>\mathbf{proc}\ </math>, p(y); <math>\mathbf{call}\ </math>, q(y); <math>\mathbf{call}\ </math>, q(y);
   
   
   <math>\mathbf{begin}\,</math>
   <math>\mathbf{begin}\ </math>,
     <math>\mathbf{proc}\,</math> q(x); x := x+x;
     <math>\mathbf{proc}\ </math>, q(x); x := x+x;
     <math>\mathbf{var}\,</math> z = 2;
     <math>\mathbf{var}\ </math>, z = 2;
   
   
     <math>\mathbf{call}\,</math> p(z);
     <math>\mathbf{call}\ </math>, p(z);
   <math>\,\mathbf{end}</math>
   <math>\,\mathbf{end}</math>
  <math>\,\mathbf{end}</math>
  <math>\,\mathbf{end}</math>
Linia 339: Linia 333:




  <math>\mathbf{begin}\,</math>
  <math>\mathbf{begin}\ </math>,
   <math>\mathbf{proc}\,</math> q(x); <math>\mathbf{call}\,</math> r(x);
   <math>\mathbf{proc}\ </math>, q(x); <math>\mathbf{call}\ </math>, r(x);
   <math>\mathbf{proc}\,</math> p(y);
   <math>\mathbf{proc}\ </math>, p(y);
     <math>\mathbf{begin}\,</math>
     <math>\mathbf{begin}\ </math>,
       <math>\mathbf{proc}\,</math> r(x); x := x+x;
       <math>\mathbf{proc}\ </math>, r(x); x := x+x;
   
   
       <math>\mathbf{call}\,</math> q(x);
       <math>\mathbf{call}\ </math>, q(x);
     <math>\,\mathbf{end}</math>
     <math>\,\mathbf{end}</math>
   <math>\mathbf{var}\,</math> z = 7;
   <math>\mathbf{var}\ </math>, z = 7;
   
   
   <math>\mathbf{call}\,</math> p(z);
   <math>\mathbf{call}\ </math>, p(z);
  <math>\,\mathbf{end}</math>
  <math>\,\mathbf{end}</math>


Linia 369: Linia 363:
\quad \mbox{ o ile }
\quad \mbox{ o ile }
E(x_1) = \langle x, I, E' \rangle \in \mathbf{Proc} \mbox{ i }
E(x_1) = \langle x, I, E' \rangle \in \mathbf{Proc} \mbox{ i }
E(x_2) = l \in \mathbf{Loc}.
E(x_2) = l \in \mathbf{Loc}</math>
</math>


O statyczności decyduje to, że wnętrze procedury <math>I</math> wykonywane jest w środowisku zmiejsca deklaracji <math>E'</math>.
O statyczności decyduje to, że wnętrze procedury <math>I</math> wykonywane jest w środowisku zmiejsca deklaracji <math>E'</math>.
Linia 380: Linia 373:
\quad \mbox{ o ile }
\quad \mbox{ o ile }
E(x_1) = \langle x, I, E' \rangle \in \mathbf{Proc} \mbox{ i }
E(x_1) = \langle x, I, E' \rangle \in \mathbf{Proc} \mbox{ i }
E(x_2) = l \in \mathbf{Loc}.
E(x_2) = l \in \mathbf{Loc}</math>
</math>


Oczywiście w takim przypadku w środowiskach wystarczy przechowywać dla procedur pary <math>\langle x, I \rangle</math>.
Oczywiście w takim przypadku w środowiskach wystarczy przechowywać dla procedur pary <math>\langle x, I \rangle</math>.
Linia 401: Linia 393:




  <math>\mathbf{begin}\,</math>
  <math>\mathbf{begin}\ </math>,
   <math>\mathbf{proc}\,</math> p(x); <math>\mathbf{if}\,</math> x < 100 <math>\,\mathbf{then}\,</math> x := x+x; <math>\mathbf{call}\,</math> p(x) <math>\,\mathbf{else}\, \mathbf{skip}</math>;
   <math>\mathbf{proc}\ </math>, p(x); <math>\mathbf{if}\ </math>, x < 100 <math>\,\mathbf{then}\ </math>, x := x+x; <math>\mathbf{call}\ </math>, p(x) <math>\,\mathbf{else}\, \mathbf{skip}</math>;
   <math>\mathbf{var}\,</math> z = 8;
   <math>\mathbf{var}\ </math>, z = 8;
   
   
   <math>\mathbf{call}\,</math> p(z);
   <math>\mathbf{call}\ </math>, p(z);
  <math>\,\mathbf{end}</math>
  <math>\,\mathbf{end}</math>


Linia 432: Linia 424:




{{rozwiazanie|


<div class="mw-collapsible mw-made=collapsible mw-collapsed">
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
Linia 478: Linia 469:
</math>
</math>
<math>
<math>
E(x_1) = \langle x, I, E' \rangle \in \mathbf{Proc} \mbox{ i } l = \mathtt{newloc}(s).
E(x_1) = \langle x, I, E' \rangle \in \mathbf{Proc} \mbox{ i } l = \mathtt{newloc}(s)</math>  
</math>  


</div></div>
</div></div>
Linia 501: Linia 491:
e \, ::= \,\,
e \, ::= \,\,
           \ldots \,\,|\,\,
           \ldots \,\,|\,\,
           \mathbf{call}\, x_1(x_2).
           \mathbf{call}\, x_1(x_2)</math>
</math>


Wewnątrz funkcji jej nazwą można posługiwać się jak zmienną lokalną.
Wewnątrz funkcji jej nazwą można posługiwać się jak zmienną lokalną.

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

Zawartość

Ostatnie zajęcia poświęcone semantyce naturalnej. Rozszerzymy język TINY o deklaracje zmiennych i procedur z jednym parametrem. Rozważymy statyczną i dynamiczną widoczność (wiązanie) identyfikatorów oraz różne mechanizmy przekazywania parametrów. Pracujemy ze środowiskami i stanami.


Semantyka naturalna procedur

Ćwiczenie 1 (procedury)

Rozszerzmy język TINY o deklaracje i wywołania procedur:

I::=|𝐛𝐞𝐠𝐢𝐧d;I𝐞𝐧𝐝|𝐜𝐚𝐥𝐥x1(x2)

d::=𝐯𝐚𝐫x=e|𝐩𝐫𝐨𝐜x1(x2);I|d1;d2

Konstrukcja 𝐩𝐫𝐨𝐜x1(x2) deklaruje procedurę o nazwie x1, której parametrem formalnym jest x2. Zakładamy statyczne wiązanie identyfikatorów i przekazywanie parametrów przez zmienną (to znaczy, że w momencie wywołania procedury powinna zostać przekazana lokacja odpowiadająca parametrowi aktualnemu). Instrukcja 𝐜𝐚𝐥𝐥x1(x2) wywołuje procedurę x1 z parametrem aktualnym x2.


Rozwiązanie


Ćwiczenie 2 (wiązanie dynamiczne)

Zastanówmy się, jakich modyfikacji wymaga nasza semantyka, aby wiązanie identyfikatorów było dynamiczne zamiast statycznego. Rozumiemy przez to, że w przypadku odwołania do zmiennej wewnątrz procedury, odwołujemy się do środowiska w miejscu wywołania tej procedury, zamiast do środowiska z miejsca deklaracji jak dotychczas. Tak samo powinno być w przypadku wywołania innej procedury wewnątrz procedury, czyli wiązanie dynamiczne dotyczy i zmiennych i procedur.


Przykład

Spójrzmy na kilka prostych programów.

𝐛𝐞𝐠𝐢𝐧 ,
  𝐯𝐚𝐫 , x = 1;
  𝐩𝐫𝐨𝐜 , p(y); y := y+x;

  𝐛𝐞𝐠𝐢𝐧 ,
    𝐯𝐚𝐫 , x = 10; 𝐯𝐚𝐫 , z = 0;

    𝐜𝐚𝐥𝐥 , p(z);
  𝐞𝐧𝐝
𝐞𝐧𝐝


Wartość końcowa zmiennej z=10. Gdyby wiązanie zmiennej x było statyczne, to wartość ta wynosiłaby 1. Podobnie dla procedur:


𝐛𝐞𝐠𝐢𝐧 ,
  𝐩𝐫𝐨𝐜 , q(x); x := x+1;
  𝐩𝐫𝐨𝐜 , p(y); 𝐜𝐚𝐥𝐥 , q(y); 𝐜𝐚𝐥𝐥 , q(y);

  𝐛𝐞𝐠𝐢𝐧 ,
    𝐩𝐫𝐨𝐜 , q(x); x := x+x;
    𝐯𝐚𝐫 , z = 2;

    𝐜𝐚𝐥𝐥 , p(z);
  𝐞𝐧𝐝
𝐞𝐧𝐝


Wartość końcowa zmiennej z=8. Gdyby widoczność procedury q była statyczna, to wartość ta wynosiłaby 4. A oto przykład programu, który nie wykonałby się poprawnie przy wiązaniu statycznych, a wykonuje się poprawnie przy dynamicznym:


𝐛𝐞𝐠𝐢𝐧 ,
  𝐩𝐫𝐨𝐜 , q(x); 𝐜𝐚𝐥𝐥 , r(x);
  𝐩𝐫𝐨𝐜 , p(y);
    𝐛𝐞𝐠𝐢𝐧 ,
      𝐩𝐫𝐨𝐜 , r(x); x := x+x;

      𝐜𝐚𝐥𝐥 , q(x);
    𝐞𝐧𝐝
  𝐯𝐚𝐫 , z = 7;

  𝐜𝐚𝐥𝐥 , p(z);
𝐞𝐧𝐝


Wartość końcowa zmiennej z wynosi 14. Procedura p wywołuje procedurę q "przekazując" jej również środowisko z miejsca wołania, zawierające informację o procedurze r. Ta ostatnia przy widoczności statycznej byłaby lokalna, a teraz nie jest.


Rozwiązanie


Ćwiczenie 3 (różne mechanizmy przekazywana parametru)

Rozważ inne mechanizmy przekazywania parametru (wiązanie statyczne):

  • przez wartość
  • in-out

Należy wyjaśnić ostatni mechanizm (in-out). Parametrem aktualnym jest zmienna, której wartość jest przypisywana parametrowi formalnemu (tak jak przy przekazywaniu przez wartość, gdy parametrem aktualnym jest zmienna). Ale po zakończeniu procedury, wartość parametru formalnego, która mogła zmienić się w czasie dzialania procedury, jest z powrotem przypisywana na zmienną będącą parametrem aktualnym (a więc podobnie do przekazywania przez zmienną). Parametr formalny jest traktowany jak zmienna lokalna procedury.


Rozwiązanie (przekazywanie parametru przez wartość)


Rozwiązanie (przekazywanie parametru in-out)

Zadania domowe

Ćwiczenie 1

Zaadaptuj semantykę "deklaracji równoległych" dla rekurencji wzajemnej wewnątrz jednej deklaracji równoległej. To znaczy, że procedury zadeklarowane w jednej deklaracji równoległej mogą się wzajemniej wywoływać bez żadnych ograniczeń.


Ćwiczenie 2

Zamiast procedur, rozważ funkcje z pojedynczym parametrem przekazywanym przez zmienną. Wywołanie funkcji może teraz pojawić się wewnątrz wyrażenia:

e::=|𝐜𝐚𝐥𝐥x1(x2)

Wewnątrz funkcji jej nazwą można posługiwać się jak zmienną lokalną. Wynik zwracany przez funkcję to wartość tej zmiennej w momencie wyjścia z funkcji.

Uwaga na efekty uboczne!


Ćwiczenie 3

Rozważ następujące warianty:

  • wiązanie zmiennych jest statyczne, a procedur dynamiczne
  • wiązanie zmiennych jest dynamiczne, a procedur statyczne.


Ćwiczenie 4

Rozszerz semantykę procedur tak, aby parametrem aktualnym procedury mogła być procedura.