###### tags: `MP` # III tercja wykład 1 ## O czym będziemy mówić W III tercji będziemy (wstępnie) mówić o tym, jak rozumieć (głębiej) konstrukcje językowe. Przede wszystkim będziemy patrzeć na Racketa i Plaita. Podstawowe 3 aspekty języka: 1. składnia (konkretna / abstrakcyjna) 2. semantyka (wiedza o tym, jakie jest znaczenie konstrukcji) 3. pragmatyka (jak się języka używa, nie będziemy o tym mówić) Będziemy się zajmować przede wszystkim semantyką (wyrażona w terminach interpreterów). Być może będziemy pisać coś zgadującego typy. Interpretery będziemy pisać w języku Plait (to będzie nasz meta-język). ## Informacje Wszystkie pliki z wykładu, o których będzie opowiadane "Rozszerz" oznacza, że należy rozszerzyć: 1. składnię abstrakcyjną 2. interpreter 3. składnię konkretną (poprzez rozszerzenie parsera) ## Parser Ostatnio mieliśmy parser Racketa w Plaicie (chyba). Mamy w Plaicie statyczne typy danych. Budowanie parserów jest odrębną rzeczą i się tego nie robi (są programy do automatycznej budowy parserów na podstawie gramatyki). ## Język wyrażeń arytmetycznych: Składnia abstrakcyjna: 1. Wyrażenia to: * stała (numer) * operator (binarny) z dwoma wyrażeniami Parser: zamienia postać "liniową" z wejścia na drzewko Parser zawsze działa na S-wyrażeniach (atomy i zagnieżdzone listy). Przyjmiemy konwencję, że będziemy użuwać nawiasów figurowych, czyli {}. ## Testowanie Plait ma mechanizm na tworzenie modułu do testowania: ```plait (module+ test (test (parse '2); poprawne wyniki (numE 2)) ... (test/exn (parse '{{+ 1 2}}) ;upewniamy się, że jak powiny być błędy to są "invalid input")) ``` Ważne: testowanie możemy zrobić na początku pliku i to i tak będzie działać. ## Interpretowanie 1. Ustalenie dziedziny wartości interpretera (dla wyrażeń arytmetycznych trywialne) alias typu: nadanie nowej nazwy istniejącemu typowi ## Inne sposoby pisania interpretera Można zbudować maszynę abstrakcyjną interpretującą rzeczy (jak wyglądają przejścia pomiędzy stanami). Wtedy obliczenie to pewien ciąg przejść po którym (liczymy, że) dojdziemy do stanu końcowego. Można w interpreterze ogarnąć wstawianie rzeczy na stos za Plaita (bo i tak by to sam zrobił). Taka wersja jest prostsza do zrobienia niskopoziomowo, bo poprzednia była bardziej wysokopoziomowa. Tutaj nasze stany są postaci: 1. <wyrazenie, stos> 2. <inne_wyrazenie, inny_stos> 3. <nowy_stos, wartosc> ## Kompilatory Interpretery są spoko do zrozumienia jak działa język itp, ale jest powolne i lepiej jest używać kompilatora. Byte code - kod w postaci listy prostych instrukcji, coś podobnego do assemblera ale "wersja idealna" **"Od tej pory wszyscy będą cytować ten kod. Cały świat."** `cond` to lukier syntaktyczny na kaskadę `if`-ów. "Tak się oczywiście tego nie robi. Ja pozwolę Państwu naprawić to w ramach listy zadań" "Jak nie wiadomo co zrobić to można dać 42." Moglibyśmy napisać też 42/0 bo wtedy byłby błąd. Nie chcemy wyrzucać błędu, ponieważ w tym momencie dopiero interpretujemu kod, dopóki nie jest uruchomiony wurzucanie errorów nie ma sensu. Później będzie jak to można inaczej zrobić. Generalnie piszemy Racketa w Plaicie ale bez zmiennych. Monady: Na poziomie programowania to sposób na narzucenie programowi struktury i określenie co i jak się policzy: 1. jak wygląda ... 2. funkcja return 3. funkcja bind (jak złożyć ze sobą obliczenia)