Metody realizacji języków programowania/MRJP Laboratorium: Różnice pomiędzy wersjami
luźne uwagi |
dodana część zadań, szkic kryteriów oceniania, rozszerzenia języka |
||
Linia 18: | Linia 18: | ||
operacje arytmetyczne, funkcje globalne, rekurencja (też wzajemna) | operacje arytmetyczne, funkcje globalne, rekurencja (też wzajemna) | ||
# rekordy, tablice,dynamiczna alokacja, zwalnianie jawne ('''delete''') | # rekordy, tablice,dynamiczna alokacja, zwalnianie jawne ('''delete''') | ||
# lokalne procedury | |||
# klasy deklarowane na poziomie globalnym | # klasy deklarowane na poziomie globalnym | ||
# klasy lokalne | # klasy lokalne | ||
Linia 26: | Linia 27: | ||
# dodatkowe operatory dla wyrażeń () | # dodatkowe operatory dla wyrażeń () | ||
# odśmiecanie zamiast '''delete''' | # odśmiecanie zamiast '''delete''' | ||
= Gramatyka języka = | |||
Będzie skopiowana z LaTeXa | |||
= Semantyka języka = | |||
= Wymagania implementacyjne i ocenianie = | |||
Na 3: | |||
Podstawowe konstrukcje, rekordy, tablice, dynamiczna alokacja | |||
Na 3+: | |||
Na 4: | |||
Lokalne deklaracje procedur. | |||
Na 4+: | |||
Na 5: | |||
Obiekty, operator '''instanceof''', rzutowanie (por. zadanie FIXME). | |||
Dodatkowo punktowane zadania. | |||
* Lokalne deklaracje klas, | |||
* Odśmiecanie zamiast jawnego '''delete''' | |||
= Zadania = | |||
== Zadanie 1: Inicjalizacja zmiennych == | |||
Aby język był bardziej bezpieczny chcielibyśmy wyeliminować możliwość użycia niezainicjalizowanych zmiennych. W tym celu modyfikujemy deklaracje zmiennej tak, aby podanie wartości przy deklaracji było obowiązkowe: | |||
var x : int = 5; | |||
var y : int = 3*x+5; | |||
Zastanów się, jakie ograniczenia należy wprowadzić na wyrażenia użyte do inicjalizacji aby język był całkowicie bezpieczny. Na przykład poniższa sekwencja deklaracji prowadzi do błędu: | |||
var x : int = y + 4; | |||
var y : int = x + 4; | |||
Przemyśl następujące możliwości: | |||
* dopuszczenie tylko wyrażeń stałych | |||
* dopuszczenie jedynie zmiennych zadeklarowanych wcześniej na tym samym poziomie | |||
* dopuszczenie jedynie zmiennych i funkcji zadeklarowanych wcześniej na tym samym poziomie | |||
* dopuszczenie jedynie zmiennych zadeklarowanych wcześniej na tym samym poziomie i wszystkich funkcji z tego poziomu | |||
* dopuszczenie zmiennych zadeklarowanych wcześniej na tym samym poziomie i wszystkich funkcji | |||
* dopuszczenie wszystkich zmiennych zadeklarowanych wcześniej na tym poziomie oraz wszystkich zmiennych i funkcji zakeklarowanych wyżej | |||
* oznaczanie zmiennych niezainicjalizowanych i sprawdzanie bycia zainicjalizowaną przy każdym odwołaniu | |||
Która z możliwości daje największe bezpieczeństwo? Która ma nieakceptowalny narzut czasu | |||
wykonania? Która jest najbardziej elastyczna? Czy pewne z nich pozwalają obejść zabezpieczenia? Weź pod uwagę jakie zmienne i funkcje są dostępne z wewnątrz funkcji. | |||
== Zadanie 2: Klasy wewnątrz klas == | |||
Czy klasa zadeklarowana wewnątrz innej klasy może korzystać ze zmiennych tamtej klasy? | |||
Jakie byłoby ograniczenie na możliwość tworzenia instancji klasy wewnętrznej jeśli ta klasa byłaby widoczna na zewnątrz (odp. Aby utworzyć element klasy wewnętrznej trzeba mieć instancję klasy zewnętrznej) | |||
Nie jest to wymagane gdy klasa wewnętrzna nie używa zmiennych klasy zewnętrznej - modyfikator static przy deklaracji klasy wewnętrznej w javie | |||
== Zadanie 3: Klasy wewnątrze procedur == | |||
= Rozszerzenia języka = | |||
== Inicjalizacja zmiennych == | |||
Zmień deklaracje zmiennych tak, żeby przy deklaracji w procedurze, rekordzie lub klasie (ale nie jako parametru funkcji) trzeba było (obowiązkowo!) podać wartość inicjalizacji zmiennej. Przykład: | |||
var x : int = 50; | |||
Przyjmij, że inicjalizacja tablic i rekordów następuje w momencie ich tworzenia ('''new'''): | |||
y = new int[3*x] of 5; | |||
z = new myRecord { field1 = 4, field2 = "ala ma kota"}; | |||
Przy inicjalizacji zmiennej dopuszczalne jest użycie zmiennej zadeklarowanej wyżej na tym samym poziomie, wszystkich funkcji na tym poziomie oraz wszstkich zmiennych i funkcji zadeklarowanych na poziomach wyższych. | |||
== Odśmiecanie == | |||
Usuń konstrukcję '''delete''' i zrób zamiast tego automatyczne odśmiecanie. | |||
== Ulepszenie read i write == | |||
Język Kotek zawiera bardzo prymitywne mechanizmy wejścia wyjścia. Rozszesz język o: | |||
* możliwość odczytania wartości do pola rekordu lub klasy oraz do elementu tablicy (obecnie gramatyka dopuszcza czytanie tylko zmiennej atomowej) | |||
read a[5]; | |||
read mojRekord.pole1; | |||
* możliwość czytania i pisania wielu wartości na raz | |||
read a[i], b[i]; | |||
write "a[5] = ", a[5]; | |||
== Rzutowanie i sprawdzanie typu obiektu == | |||
Język nie zawiera rzutowania na typy. Jest to konstrukcja bardzo często wykorzystywana w programowaniu obiektowym, gdy trzeba zrzutować obiekt na typ podlkasy. Do tego jest też potrzebne sprawdzanie, czy obiekt jest elementem danej klasy. | |||
Rozszerz język o konstrukcję rzutowania: | |||
(Podklasa) mojObiekt | |||
i sprawdzania typu: | |||
obiekt instance of klasa | |||
Obie konstrukcje są wyrażeniami. Pierwsza daje typ Podklasa a druga typ int (wartosc 0 lub nie-zero) | |||
== Typ bool == | |||
W języku nie ma typu bool. Dodaj ten typ do języka. Popraw analizę semantyczną tak, aby | |||
rozróżniać typy int i bool. Rozszeż wyrażenia logiczne tak, aby | |||
a || b || c | |||
a && b && c | |||
a && b || c | |||
były poprawnymi wyrażeniami. Załóż priorytet && nad ||. | |||
== Typ zmiennoprzecinkowy == | |||
Dodaj do języka typy zmiennnoprzecinkowe: '''float''' (pojedyncza precyzja) i '''double''' (podwójna precyzja). Zmień analizę semantyczną tak, aby uwzględniała nowe typy. Dodaj operator rzutowania na nowe typy. | |||
== Chronione pola klasy == | |||
Dodaj do języka mechanizm ochrony deklaracji klasowych. Deklaracja będzie rozszerzona o modyfikator '''private''', '''public''' i '''protected''' (obok nazwy typu deklaracji): | |||
var private x : int; | |||
function public f() : bool; | |||
type protected typ = { var x: int; var y : int }; | |||
Deklaracje '''public''' mają być widoczne zawsze, '''private''' tylko wewnątrz klasy a '''protected''' wewnątrz klasy i w podklasach. |
Wersja z 07:52, 30 lip 2006
Język kotek
Imperatywny, podobny do Pascala język programowania
Cechy:
- zwykłe konstrukcje: pętle for i while, wyrażenia arytmetyczne, logiczne
- silne typowanie
- funkcje
- tablice, rekordy
- klasy
- dynamiczna alokacja obiektów,rekordów i tablic (tylko na stercie)
- zagnieżdżone deklaracje funkcji
- zagnieżdżone (w klasach, funkcjach i metodach) deklaracje klas
Etapy pisania kompilatora
- podstawowe konstrukcje: for, while, zmienne tylko typu int i string, proste
operacje arytmetyczne, funkcje globalne, rekurencja (też wzajemna)
- rekordy, tablice,dynamiczna alokacja, zwalnianie jawne (delete)
- lokalne procedury
- klasy deklarowane na poziomie globalnym
- klasy lokalne
- deklaracje zmiennej z podaną wartością do inichalizacji
Możliwe rozszerzenia
- zmienne double, boolean
- dodatkowe operatory dla wyrażeń ()
- odśmiecanie zamiast delete
Gramatyka języka
Będzie skopiowana z LaTeXa
Semantyka języka
Wymagania implementacyjne i ocenianie
Na 3: Podstawowe konstrukcje, rekordy, tablice, dynamiczna alokacja
Na 3+:
Na 4: Lokalne deklaracje procedur.
Na 4+:
Na 5: Obiekty, operator instanceof, rzutowanie (por. zadanie FIXME).
Dodatkowo punktowane zadania.
- Lokalne deklaracje klas,
- Odśmiecanie zamiast jawnego delete
Zadania
Zadanie 1: Inicjalizacja zmiennych
Aby język był bardziej bezpieczny chcielibyśmy wyeliminować możliwość użycia niezainicjalizowanych zmiennych. W tym celu modyfikujemy deklaracje zmiennej tak, aby podanie wartości przy deklaracji było obowiązkowe:
var x : int = 5; var y : int = 3*x+5;
Zastanów się, jakie ograniczenia należy wprowadzić na wyrażenia użyte do inicjalizacji aby język był całkowicie bezpieczny. Na przykład poniższa sekwencja deklaracji prowadzi do błędu:
var x : int = y + 4; var y : int = x + 4;
Przemyśl następujące możliwości:
- dopuszczenie tylko wyrażeń stałych
- dopuszczenie jedynie zmiennych zadeklarowanych wcześniej na tym samym poziomie
- dopuszczenie jedynie zmiennych i funkcji zadeklarowanych wcześniej na tym samym poziomie
- dopuszczenie jedynie zmiennych zadeklarowanych wcześniej na tym samym poziomie i wszystkich funkcji z tego poziomu
- dopuszczenie zmiennych zadeklarowanych wcześniej na tym samym poziomie i wszystkich funkcji
- dopuszczenie wszystkich zmiennych zadeklarowanych wcześniej na tym poziomie oraz wszystkich zmiennych i funkcji zakeklarowanych wyżej
- oznaczanie zmiennych niezainicjalizowanych i sprawdzanie bycia zainicjalizowaną przy każdym odwołaniu
Która z możliwości daje największe bezpieczeństwo? Która ma nieakceptowalny narzut czasu wykonania? Która jest najbardziej elastyczna? Czy pewne z nich pozwalają obejść zabezpieczenia? Weź pod uwagę jakie zmienne i funkcje są dostępne z wewnątrz funkcji.
Zadanie 2: Klasy wewnątrz klas
Czy klasa zadeklarowana wewnątrz innej klasy może korzystać ze zmiennych tamtej klasy? Jakie byłoby ograniczenie na możliwość tworzenia instancji klasy wewnętrznej jeśli ta klasa byłaby widoczna na zewnątrz (odp. Aby utworzyć element klasy wewnętrznej trzeba mieć instancję klasy zewnętrznej) Nie jest to wymagane gdy klasa wewnętrzna nie używa zmiennych klasy zewnętrznej - modyfikator static przy deklaracji klasy wewnętrznej w javie
Zadanie 3: Klasy wewnątrze procedur
Rozszerzenia języka
Inicjalizacja zmiennych
Zmień deklaracje zmiennych tak, żeby przy deklaracji w procedurze, rekordzie lub klasie (ale nie jako parametru funkcji) trzeba było (obowiązkowo!) podać wartość inicjalizacji zmiennej. Przykład:
var x : int = 50;
Przyjmij, że inicjalizacja tablic i rekordów następuje w momencie ich tworzenia (new):
y = new int[3*x] of 5; z = new myRecord { field1 = 4, field2 = "ala ma kota"};
Przy inicjalizacji zmiennej dopuszczalne jest użycie zmiennej zadeklarowanej wyżej na tym samym poziomie, wszystkich funkcji na tym poziomie oraz wszstkich zmiennych i funkcji zadeklarowanych na poziomach wyższych.
Odśmiecanie
Usuń konstrukcję delete i zrób zamiast tego automatyczne odśmiecanie.
Ulepszenie read i write
Język Kotek zawiera bardzo prymitywne mechanizmy wejścia wyjścia. Rozszesz język o:
- możliwość odczytania wartości do pola rekordu lub klasy oraz do elementu tablicy (obecnie gramatyka dopuszcza czytanie tylko zmiennej atomowej)
read a[5]; read mojRekord.pole1;
- możliwość czytania i pisania wielu wartości na raz
read a[i], b[i]; write "a[5] = ", a[5];
Rzutowanie i sprawdzanie typu obiektu
Język nie zawiera rzutowania na typy. Jest to konstrukcja bardzo często wykorzystywana w programowaniu obiektowym, gdy trzeba zrzutować obiekt na typ podlkasy. Do tego jest też potrzebne sprawdzanie, czy obiekt jest elementem danej klasy.
Rozszerz język o konstrukcję rzutowania:
(Podklasa) mojObiekt
i sprawdzania typu:
obiekt instance of klasa
Obie konstrukcje są wyrażeniami. Pierwsza daje typ Podklasa a druga typ int (wartosc 0 lub nie-zero)
Typ bool
W języku nie ma typu bool. Dodaj ten typ do języka. Popraw analizę semantyczną tak, aby rozróżniać typy int i bool. Rozszeż wyrażenia logiczne tak, aby
a || b || c a && b && c a && b || c
były poprawnymi wyrażeniami. Załóż priorytet && nad ||.
Typ zmiennoprzecinkowy
Dodaj do języka typy zmiennnoprzecinkowe: float (pojedyncza precyzja) i double (podwójna precyzja). Zmień analizę semantyczną tak, aby uwzględniała nowe typy. Dodaj operator rzutowania na nowe typy.
Chronione pola klasy
Dodaj do języka mechanizm ochrony deklaracji klasowych. Deklaracja będzie rozszerzona o modyfikator private, public i protected (obok nazwy typu deklaracji):
var private x : int; function public f() : bool; type protected typ = { var x: int; var y : int };
Deklaracje public mają być widoczne zawsze, private tylko wewnątrz klasy a protected wewnątrz klasy i w podklasach.