SW wykład 2 - Slajd13
Składnia Składnia konkretna Składnia abstrakcyjna Przyjmowane założenia Przykład wiodący Kategorie składniowe Kategorie składniowe, c.d. Uwagi Indukcja strukturalna Definicje indukcyjne Kategorie semantyczne Wartościowanie zmiennych Semantyka wyrażeń Semantyka wyrażeń logicznych Semantyka instrukcji Prosty fakt Dowód Przezroczystość odwołań Semantyka operacyjna Obliczenia Semantyka operacyjna Tiny Własności Własności, c.d. Warianty definicji

Teraz już jesteśmy gotowi podać definicję semantyki wyrażeń arytmetycznych. Wartość wyrażenia arytmetycznego zależy oczywiście od wartościowania (występujących w nim) zmiennych. Zatem znaczeniami wyrażeń są funkcje, które stanom przypisują liczby całkowite. Znaczenia te definiujemy przez indukcję strukturalną po strukturze wyrażenia. Dla każdej możliwej postaci wyrażenia arytmetycznego (czyli dla każdej konstrukcji językowej budującej wyrażenie z jego bezpośrednich składowych; czyli dla każdej produkcji gramatyki bezkontekstowej określającej składnię wyrażeń) podajemy jego znaczenie, wykorzystując jako dane znaczenia jego bezpośrednich składowych. Oczywiście, w klauzulach definicji wykorzystujemy standardowe operacje arytmetyczne na liczbach: dodawanie, mnożenie i odejmowanie (uwaga na zmianę kolorów: odpowiadające im syntaktyczne symbole są tu brązowe, a same operacje oznaczane są symbolami czarnymi --- mamy nadzieję, że choć trochę jest to widoczne na slajdach). Uwaga też na semantykę wyrażeń będących zmiennymi: w oczywisty sposób korzystamy tu ze sposobu semantycznego reprezentowania wartościowania zmiennych jako funkcji.
Zdefiniowaliśmy w ten sposób powyżej funkcję, która każdemu wyrażeniu arytmetycznemu przypisuje jego znaczenie. Znaczenia te z kolei też są funkcjami, przypisującymi wartości liczbowe stanom. To właśnie mówi podany na początku slajdu "typ" funkcji semantycznej dla wyrażeń, wykorzystujący dość oczywistą (mamy nadzieję) notację dla oznaczenia zbiorów funkcji.
Funkcja semantyczna dla wyrażeń to prościutki przykład funkcji wyższego rzędu. Znacznie bardziej "zagnieżdżone" funkcje wyższego rzędu, których argumentami i wynikami są funkcje (być może znów wyższego rzędu), wykorzystywać będziemy w przyszłości bez dalszych uwag i ostrzeżeń.
Wśród takich funkcji najczęściej bodaj wykorzystywać będziemy funkcje, które można utożsamiać z funkcjami wieloargumentowymi (przynajmniej dopóki nie mamy do czynienia z funkcjami częściowymi), ale które nie muszą otrzymywać wszystkich swoich argumentów "od razu", a mogą je przyjmować pojedynczo w pewnej ustalonej kolejności. Są to funkcje, które otrzymując argument dają w wyniku funkcję, która otrzymując (kolejny) argument daje w wyniku funkcję, która otrzymując (kolejny) argument daje w wyniku funkcję, ..., która otrzymując (ostatni) argument, daje wynik. Znane choćby z programowania funkcyjnego operatory pozwalają przekształcać tak "rozwinięte" funkcje do postaci "zwiniętej", gdzie wszystkie argumenty od pierwszego do ostatniego muszą być podane od razu. Stosując funkcje w takiej rozwiniętej postaci do kolejnych argumentów, często bardzo oszczędnie wykorzystywać będziemy nawiasy, przyjmując zawsze, że aplikacja łączy sie do lewej: na przykład, F x y oznacza (F(x))(y).