Podejście stosowe

Download Report

Transcript Podejście stosowe

Podejście stosowe do obiektowych języków
programowania baz danych
http://www.sbql.pl
Wykładowca: Kazimierz Subieta
Polsko-Japońska Wyższa Szkoła
Technik Komputerowych, Warszawa
[email protected]
http://www.ipipan.waw.pl/~subieta
© K.Subieta. Podejście stosowe 13, Folia 1
Wykład 13
Mocna kontrola typów (1)
Po co są typy?
 Istotnym składnikiem języka programowania jest system kontroli
typologicznej.
 Chroni on programistów przed ich własnymi błędami, stąd jest
kluczowym czynnikiem podwyższenia niezawodności oprogramowania.
• Istnieją szacunki pokazujące, że system kontroli typologicznej jest w stanie
wykryć 80% błędów semantycznych i koncepcyjnych.
• Wzrostu wydajności programistów, szczególnie w fazie pielęgnacji
• Bezpieczeństwo typologiczne (typing safety) jako podstawowa zasada języków
programowania.
 System typów ma również znaczenie dla modelowania pojęciowego, gdyż
typy pełnią rolę semantyczną w dziedzinie przedmiotowej.
• Np. typ Student przypisany do obiektu zdradza nam jego intencję i biznesową
semantykę.
 Typy przenoszą także informację o metodzie reprezentacji danych
wewnątrz pamięci komputera (ważne dla standardów, np. CORBA).
 Języki bez mocnej kontroli typów są uważane za niebezpieczne,
prowadzące do niskiej jakości oprogramowania.
© K.Subieta. Podejście stosowe 13, Folia 2
Dlaczego typy nie zawsze są doceniane? (1)
 Jakość i niezawodność oprogramowania nie zawsze jest priorytetem
działania firm komercyjnych.
 Wprowadzenie typów do języka wymaga odpowiedniej kompetencji
w tym zakresie, która często nie jest właściwa decydentom i twórcom
języków wywodzącym się z tych kręgów.
• Nieliczne uczelnie prowadzą w tym zakresie wykłady i ćwiczenia.
• Niektóre z nich traktują typy jako okazję do prezentowania (wyrafinowanych,
lecz niepraktycznych) teorii matematycznych w zakresie typów, a nie do
objaśniania rzeczywistych problemów i rozwiązań.
• Przełożenie tych teorii na efektywną implementację jest zwykle trudne lub
niemożliwe, a najczęściej (z powodu ograniczeń teorii) bezsensowne.
 Implementacja kontroli typologicznej jest dodatkowym obciążeniem dla
twórców języka lub systemu, zwiększającym koszt i czas wytworzenia
odpowiedniego oprogramowania.
 Programy uwzględniające kontrolę typologiczną są dłuższe (chociaż
zwykle bardziej czytelne, ze względu na modelowanie pojęciowe).
© K.Subieta. Podejście stosowe 13, Folia 3
Dlaczego typy nie zawsze są doceniane? (2)
 Język z mocną kontrolą typów traci część elastyczności.
 Zwykle oznacza bardziej sztywne struktury danych, co może być
nieakceptowalne dla rozluźnionych formatów, np. dla XML.
• W Pascalu zbyt mocna kontrola typologiczna uniemożliwia m.in. napisanie
procedury mnożącej dwie macierze o dowolnych wymiarach.
 Język z mocną kontrolą typów bardzo utrudnia programowanie
generyczne, przy którym docelowy typ przetwarzanego obiektu nie jest
znany w czasie kompilacji.
• Programowanie generyczne wymaga odzyskania informacji o strukturze/typie
obiektu podczas wykonania programu i zastosowanie do niego
przetwarzania.
 Ten aspekt zaowocował rodziną języków programowania tzw.
polimorficznych, których najwybitniejszym przykładem jest SML.
• Ta linia języków programowania nie sprawdziła się jak dotąd
w powszechnym programowaniu.
• Podstawową metodą programowania generycznego jest refleksja (znana m.in.
z dynamicznego SQL i DII CORBA), która w istocie utrudnia lub
uniemożliwia mocną statyczną kontrolę typów.
© K.Subieta. Podejście stosowe 13, Folia 4
Co to jest system typów?
 Typ jest formalnym ograniczeniem narzuconym na budowę bytu
programistycznego lub jest specyfikacją jego parametrów i wyniku.
 Z drugiej strony, typ jest formalnym ograniczeniem kontekstu, w którym
odwołanie do tego bytu może być użyte w programie.
 System typów języka programowania polega na przypisywaniu wyrażeń
oznaczających typy bytom występującym w programie (obiektom,
funkcjom, procedurom, metodom itd.), oraz sprawdzanie zgodności
użycia danego bytu w programie z jego zadeklarowanym typem.
 Typów używa się także do dynamicznej kontroli poprawności budowy
obiektów
• Patrz np. DTD lub XMLSchema dla plików XML.
 Jest to istotna, ale raczej drugorzędna rola systemu typów, która w
klasycznych językach programowania i językach baz danych nie
występuje.
© K.Subieta. Podejście stosowe 13, Folia 5
Typy a schematy baz danych (1)
 Tradycyjnie typy są własnością programów.
 W związku z niezależnością danych nastąpiło przesunięcie typów na
stronę danych.
 W ten sposób pojawiło się pojęcie schematu bazy danych.
 Schemat pełni dwie role.
• Informuje programistę o tym, co baza danych zawiera i jak jest
zorganizowana.
• Jest wykorzystywany przez SZBD do kontroli danych zapamiętanych w bazie
danych.
 Schemat bazy danych zwalnia języki programowania z obowiązku
trzymania informacji typologicznej.
 Kompilator języka powinien odczytać typ ze schematu zapamiętanego
w bazie danych.
 Typy przyjmują postać niezależną od konkretnego języka programowania.
• Patrz np. system typów standardu OMG CORBA oraz standardu ODMG.
• W ramach platformy .NET powstaje zunifikowany system typów dla
wszystkich języków programowania.
© K.Subieta. Podejście stosowe 13, Folia 6
Typy a schematy baz danych (2)
 Często podkreśla się podobieństwo typów znanych z języków
programowania do schematów znanych z baz danych.
 Schematy bazy danych nie definiują jednak wyłącznie typów, gdyż ich
podstawową funkcją jest modelowanie pojęciowe.
• Schematy są tym, co w języku programowania nazywa się deklaracją.
• Schematy łączą deklarowanie zmiennych, obiektów, tabel lub innych bytów
bazy danych z określaniem ich typu.
• Przykładowo, możemy mieć następującą definicję typu TypPrac:
typedef TypPrac  struct{ NrPrac:int, Nazwisko:string, Zar:int };
Tę definicję można wykorzystać do deklaracji zmiennej MójPrac:
MójPrac : TypPrac;
 W schematach baz danych konstrukcją semantycznie równoważną jest
wyrażenie, w którym nazwę typu tekstowo zastąpiliśmy prawą stroną
definicji typu:
MójPrac : struct{ NrPrac:int, Nazwisko:string, Zar:int};
 W schemacie konstrukcje typedef mogą występować lub nie.
• Przykładowo, w schematach zapisanych w SQL-92 nie występują.
© K.Subieta. Podejście stosowe 13, Folia 7
Strukturalna zgodność typów
 Z powodu lepszego modelowania pojęciowego, krótszego kodu oraz
zwiększenia potencjału dla ponownego użycia definicje typów określające
ich nazwy (po lewej stronie) oraz wyrażenie definiujące (po prawej
stronie) są cechą większości znanych języków i systemów.
 O takich konstrukcjach mówi się niekiedy jako o typach definiowanych
przez użytkownika (user-defined types).
 Z powodu semantycznej równoważności typy definiowane przez
użytkownika nie są składnikiem formalnej semantyki schematu
(abstrahującej od modelowania pojęciowego).
 Nazwy typów występujące w deklaracjach są tekstowo rozwijane do
pełnej postaci, z użyciem prawych stron definicji typów.
 Takie podejście jest określane jako strukturalna zgodność typów.
• W strukturalnej zgodności typów ich nazwy nie mają znaczenia.
• Liczy się tylko czy definiowane struktury danych są takie same.
© K.Subieta. Podejście stosowe 13, Folia 8
Nazwowa zgodność typów
 Większość języków programowania przyjmuje zgodność typów, określaną jako
zgodność nazwową (często kombinowaną z elementami zgodności strukturalnej).
 Przy zgodności nazwowej nazwa typu jest nośnikiem semantyki formalnej i nie
może być zastąpiona przez prawą stronę definicji nazwy typu.
• Przykładowo, jeżeli mamy dwie definicje typów:
typedef TypOsoba  struct{ Imię : string, Wiek: int };
typedef TypPies  struct{ Imię : string, Wiek: int };
to przy zgodności strukturalnej deklaracja zmiennej Florek:
Florek : TypOsoba;
jest dla kompilatora równoważna deklaracji
Florek : TypPies;
 W niektórych sytuacjach przyjęcie zgodności strukturalnej może prowadzić do
osłabienia kontroli typologicznej
• Np. zmienna typu TypPies może być użyta w kontekstach, w których oczekiwana jest
zmienna typu TypOsoba.
 Nazwowa zgodność typów rozróżnia deklaracje bytów programistycznych
wykorzystując nazwy typów.
© K.Subieta. Podejście stosowe 13, Folia 9
Statyczna i dynamiczna kontrola typologiczna
 Statyczna kontrola typów zachodzi w trakcie kompilacji programu, zaś
dynamiczna – w czasie jego wykonania.
 Kontrola dynamiczna może także dotyczyć obiektów zapamiętanych
w składzie.
• Języki takie jak DTD i XML Schema służą głównie do dynamicznej kontroli
obiektów (plików) XML.
• Nie jest jasne, czy i jak mogą być zastosowane do statycznej kontroli typów
zapytań lub programów.
 Uważa się, że skuteczna, mocna kontrola typów jest kontrolą statyczną.
 Kontrola dynamiczna jest również skuteczna, gdyż umożliwia wykrycie
błędu typologicznego podczas testowania programu.
• Wadą kontroli dynamicznej jest dodatkowe obciążenie tą kontrolą czasów
wykonania.
• Kontrola ta może być również niepełna, gdyż niemożliwe jest przetestowanie
programu na wszystkie przyszłe sytuacje, w których może on się znaleźć.
© K.Subieta. Podejście stosowe 13, Folia 10
Dynamiczna kontrola obiektów
 Często jest głoszony pogląd, że dobra, „szczelna” statyczna kontrola typologiczna
eliminuje potrzebę dynamicznej kontroli typologicznej obiektów, gdyż przy
szczelnym systemie typów nie jest możliwe wytworzenie obiektu typologicznie
niepoprawnego.
 Jest to prawda pod warunkiem, że obiekty są przetwarzane wyłącznie przez jeden
język programowania.
• W klasycznych językach programowania, takich jak C lub Pascal, obiekty (zmienne)
są upakowane oszczędnie, w postaci sekwencji bitów, zaś cała informacja
o reprezentacji wartości jest składnikiem jego typu.
• Typ z kolei jest drugiej kategorii programistycznej, czyli jest niedostępny podczas
czasu wykonania.
• Przy tym założeniu dynamiczna kontrola typu obiektu jest niemożliwa.
 To założenie nie jest spełnione dla obiektów bazy danych, które z reguły są
obsługiwane przez wiele języków i interfejsów, zazwyczaj z odmiennymi
systemami typologicznymi lub nie posiadające kontroli typologicznej.
 Niektóre opcje w językach programowania (np. warianty, wartości zerowe,
elipsy, automatyczne koercje) stwarzają nieszczelności w systemie typów,
 W takiej sytuacji kontrola dynamiczna typów obiektów jest równie ważna jak
typologiczna kontrola programów.
© K.Subieta. Podejście stosowe 13, Folia 11
Typy w językach zapytań (1)
 Teoria i praktyka typów jest w dużej mierze niezależna w stosunku do
języków zapytań.
• Na temat typów napisano tak wiele, że z pozoru wniesienie tu istotnego
wkładu jest zadaniem niemożliwym.
• W takich sytuacjach pada najczęściej sugestia zaadaptowania jednego
z istniejących systemów typów spośród propozycji przedstawionych
w rozlicznych językach, systemach, standardach lub literaturze.
 Istnieją jednak cechy języka zapytań, które wprowadzają nowe problemy
i potencjalnie nowe rozwiązania:
• Nazwa obiektu jako jego inwariant.
• Obiekty w bazie danych mają przypisane im nazwy.
• Nazwa powinna być sprawdzana typologicznie.
• Struktury, których składniki nie posiadają przypisanych im nazw.
• Najbardziej znane systemy typologiczne zakładają, że w ramach struktur każdy
element musi mieć przypisaną mu nazwę.
• Semantyka pomocniczych nazw występujących w zapytaniach
• Ta konstrukcja nie występuje w żadnym języku programowania
• Optymalizacja zapytań, która prowadzi do nowych metod kontroli typów
© K.Subieta. Podejście stosowe 13, Folia 12
Typy w językach zapytań (2) – dalsze odstępstwa
• W naszym przypadku (i w przypadku XML) pojęcie kolekcji nie zostało
wprowadzone na poziomie składu obiektów, gdyż takie potraktowanie go
prowadzi do złamania zasad obiektowości.
• Natomiast wprowadziliśmy kolekcje (bagi i sekwencje) na poziomie rezultatów
zwracanych przez zapytanie.
• Automatyczne koercje i elipsy. W językach zapytań nabierają większego
znaczenia.
• Nieregularności w danych. Dotychczasowe systemy statycznej kontroli
typologicznej ustalały nie tylko sztywny format danych, ale również
reprezentację danych.
• Dynamiczne role w modelu AS2 stwarzają nieco inną sytuację dla mocnej
kontroli typu.
• Konieczność uwzględnienia w systemie wnioskowania o typie całej sytuacji na
stosie środowiskowym, tak jak ona została opisana w poprzednich rozdziałach.
Przykładowo, zapytanie
Osoba.(Dział where Nazwa = Nazwisko)
ma sens koncepcyjny.
Czy takie zapytanie będziemy uważać za typologicznie poprawne?
© K.Subieta. Podejście stosowe 13, Folia 13
Wady istniejących systemów typologicznych
 Poza wymienionymi osobliwościami baz danych i ich języków zapytań,
mamy wiele zastrzeżeń do stosowanych w systemach obiektowych
rozwiązań typologicznych i ich teorii.
• Przykładowo, zarówno CORBA, jak i Java nie zajmują się asocjacjami, mają
też ograniczenia w zakresie definicji kolekcji.
 Próbą stworzenia systemu typów dla obiektowych baz danych był Object
Definition Language (ODL) standardu ODMG.
• Jednakże przyjęty tam polimorfizm inkluzyjny jest krytykowany jako
niespójny.
• Alternatywa F-bounded polymorphism jest niedojrzała
 Polimorfizm parametryczny (parametric polymorphism), znany z SML
i innych języków tzw. polimorficznych, pozostaje koncepcją akademicką
nie znajdującą potwierdzenia w powszechnej praktyce.
• Mimo ogromnego nacisku środowisk akademickich
• Próby implementacji: F# na platformie .Net firmy Microsoft
© K.Subieta. Podejście stosowe 13, Folia 14
Pojęcie typu
 Istnieje sporo poglądów i nieporozumień dookoła pojęć takich jak:
•
•
•
•
•
typ, klasa, interfejs,
abstrakcyjny typ danych,
dziedziczenie,
dynamiczne role obiektów.
...
 Splątanie tych pojęć w literaturze języków programowania, mnogość
definicji i różne wypowiedzi na temat ich wzajemnego stosunku
spowodowały znaczny chaos.
 Paradoksalnie, w opisie metod mocnej kontroli typu najtrudniejsze
jest wyjaśnienie, co to jest „typ”.
• Na ten temat napisano ogromną liczbę książek i artykułów.
• Ich podmiotem jest pojęcie typu zdefiniowane jako matematyczna abstrakcja.
• Sprowokowało ono teoretyków do potraktowanie typu jako pojęcia
matematycznego oraz kontroli typologicznej jako systemu formalnego
działającego na bytach matematycznych.
• Efektem jest nie uporządkowanie pojęć, lecz jeszcze większy chaos.
© K.Subieta. Podejście stosowe 13, Folia 15
Moje podejście do typów
 Będę starać się objaśnić mocną kontrolę typologiczną na gruncie
praktycznym, bez nawiązywania do niepraktycznych teorii.
• Nie będę starać się definiować pojęcia typu „jako takiego”.
• Pojęcie typu będzie więc wyjaśnione implicite, poprzez abstrakcyjną
implementację mechanizmu kontroli typologicznej.
 Nieadekwatność teorii typów polega na traktowaniu semantyki typu
jako zbioru wartości.
 W odróżnieniu przyjmiemy, że typy są tylko napisami
kwalifikującymi byty bazy danych i byty programistyczne.
 Kontrola typów polega na ustaleniu i zaimplementowaniu reguł
przekształcania specyfikacji (sygnatur) zawierających te napisy.
 Wyjaśnienie mocnej kontroli typologicznej sprowadza się do
zdefiniowania funkcji static_eval.
• Zachowanie się funkcji static_eval jest uzależnione od definicji funkcji
static_nested, konstrukcji metabazy, konstrukcji stosów S_ENVS i S_QRES
oraz reguł i metareguł wnioskowania o typie.
© K.Subieta. Podejście stosowe 13, Folia 16
Zewnętrzny i wewnętrzny system typów
 Zewnętrzny system typów jest określony przez zbiór napisów, których
intuicyjną semantyką jest wyróżnienie niezmienników budowy danego bytu
programistycznego, np. bazy danych, obiektu lub modułu.
• Przykładem jest napis integer przypisany do deklaracji pewnego obiektu.
 Zewnętrzny system typów często jest uwikłany w definicje innych
abstrakcji, np. w definicje interfejsów, klas, modułów, funkcji, metod itd.
• Często, np. w języku Pascal lub C, typ przybiera postać samodzielnego
nazwanego fragmentu tekstu programu.
 Będziemy przyjmować (w odróżnieniu od większości systemów
typologicznych), że taki nazwany fragment tekstu nie ma samodzielnej
formalnej semantyki.
• Istnieje wyłącznie jako makrodefinicja, czyli pewien nazwany napis.
• To wyklucza typy rekurencyjne, ale ich znaczenie w praktyce jest marginalne.
 Dowolna nazwa typu (poza int, float, string, bool, date, itd.) jest tylko
skrótem dla tego napisu, który ostatecznie powinien być tekstowo
rozwinięty do pełnej postaci, w której występują tylko typy atomowe.
© K.Subieta. Podejście stosowe 13, Folia 17
Statyczna symulacja procesu ewaluacji
 Mechanizm kontroli typologicznej symuluje ewaluację zapytania na bazie
tej informacji, która jest znana podczas jego parsingu (bez korzystania
z informacji zapisanych w bazie danych).
 W związku z tym statyczne stosy zawierają sygnatury obiektów z bazy
danych i operują na tych sygnaturach w sposób analogiczny do tego,
w jaki później interpreter będzie działał na konkretnych obiektach z bazy
danych.
 Operacje na statycznych stosach i sygnaturach są odpowiednikami
rzeczywistych operacji na rzeczywistych stosach i składzie danych
z pewną dokładnością,
• w szczególności nie są istotne pętle implikowane przez operatory
niealgebraiczne, a wyłącznie sygnatura wyniku działania operatora
niealgebraicznego.
© K.Subieta. Podejście stosowe 13, Folia 18
Metabaza
 Głównym składnikiem metabazy jest graf schematu bazy danych.
 Metabaza może także zawierać inne dane, np. statystyki dostępu, itd.
 Graf schematu jest wewnętrznym katalogiem danych powstałym jako
skutek kompilacji schematu danych.
 Węzły grafu zawierają definicje bytów znajdujących się w bazie danych
(obiektów, atrybutów, pointerów, klas, asocjacji itd.) oraz interfejsy metod
przechowywanych w bazie danych.
 Nazwane krawędzie grafu modelują powiązania pomiędzy definicjami.
Generalnie, może być wiele rodzajów tych powiązań.
 Dla celów kontroli typologicznej wyróżnimy spośród nich trzy:
• is_owner_of (ciągła linia), pomiędzy bytem nadrzędnym (np. definicją
obiektu) a bytem w stosunku do niego podrzędnym (np. definicją suplementu,
pointera lub metody);
• points_to (przerywana linia), pomiędzy definicją pointera a definicją obiektu,
do którego taki pointer prowadzi;
• inherits_from (podwójna linia), pomiędzy definicją klasy obiektu a definicją
jego nadklasy.
© K.Subieta. Podejście stosowe 13, Folia 19
Graf schematu - metabaza
Osoba[0..*]
Nazwisko
RokUr
Wiek()
Osoba 0..*
Zatrudnia 1..*
Prac[0..*]
NrP
Stan[1..*]
Zar[0..1]
ZmieńZar(nowyZar)
ZarNetto( )
Kieruje[0..1]
PracujeW
Szef
Zatrudnia[1..*]
Dział [0..*]
NrD
Nazwa
Lokacja[1..*]
BudżetRoczny()
© K.Subieta. Podejście stosowe 13, Folia 20
Nazwisko 1
string
RokUr 1
int
PracujeW 1
Wiek 1
void  int
Szef 1
NrD 1
int
NrP 1
int
Stan 1..*
string
Kieruje 0..1
Nazwa 1
string
Lokacja 1..*
string
Zar 0..1
int
ZmieńZar
0
nowyZar:int  void
Dział 0..*
Prac 0..*
ZarNetto 1
void  int
BudżetRoczny
void  int
1
Informacje w węzłach grafu schematu
 Pozostałe informacje o schemacie przechowywane są w węzłach. Każdy
węzeł zawiera pięć informacji:
• Wewnętrzny identyfikator węzła grafu, który będzie służył jako jednoznaczna
referencja do tego węzła we wszystkich innych miejscach mechanizmu optymalizacji
(w szczególności na stosach S_ENVS i S_QRES);
• Informację, czy dany byt jest obiektem z identyfikatorem startowym (korzeniowym),
od nazwy którego może rozpocząć się zapytanie;
• Zewnętrzną nazwę danego bytu (używaną w zapytaniach);
• Ograniczenie liczności definiowanego bytu w bazie danych;
• Typ wartości danego bytu. Typem może być typ elementarny (int, string itd.),
specyfikacja wejścia i wyjścia (sygnatura) procedury lub metody, referencje do
definicji obiektów podrzędnych w grafie schematu lub referencja do definicji obiektu,
do którego prowadzi definicja pointera.
 Dalej referencje do węzłów grafu będziemy je oznaczać inazwaWęzła, gdzie
nazwaWęzła jest nazwą umieszczoną w pierwszym polu na tym rysunku.
 Drugie pole zawiera liczność definiowanego bytu w składzie danych.
 Trzecie (dolne) pole zawiera typ, zestaw referencji do podobiektów, a dla
procedur lub metod zawiera parę t1  t2, gdzie t1 jest ciągiem nazw
i typów parametrów wejściowych, zaś t2 jest typem wyjściowym.
© K.Subieta. Podejście stosowe 13, Folia 21
Stosy statyczne
 Zadaniem stosów statycznych jest dokładne zasymulowanie działania
ewaluacji zapytań podczas czasu ich kompilacji.
 Wprowadzamy dwa takie stosy statyczne: S_ENVS i S_QRES (dla
symulacji stosów ENVS i QRES).
• Stosy statyczne zawierają sygnatury.
• Sygnatury są opisami odpowiednich bytów przechowywanych na stosach
podczas ewaluacji zapytań.
 Zwrócimy uwagę że podana dalej definicja sygnatury jest rekurencyjna.
 Stos S_ENVS zawiera statyczne bindery, tj. pary o postaci
n(sygnatura)
© K.Subieta. Podejście stosowe 13, Folia 22
Definicja sygnatury
 Każdy typ elementarny należy do zbioru Sygnatura.
 Każda referencja do węzła grafu schematu należy do zbioru Sygnatura.
 Każdy literał należy do zbioru Sygnatura. Opcja ta jest potrzebna dla
typów wyliczeniowych (enumeration) (określanych niżej jako variant).
 Jeżeli x  Sygnatura, zaś n  N, wówczas para n(x)  Sygnatura. Taki
rezultat (nazwaną sygnaturę) będziemy nazywać statyczny binder.
 Jeżeli x1, x2, ...  Sygnatura, wówczas struct{ x1, x2, ...}  Sygnatura.
 Jeżeli x1, x2, ...  Sygnatura, wówczas variant{ x1, x2, ...}  Sygnatura.
Opcja ta jest potrzebna w przypadku, gdy opisywany byt czasu wykonania
może mieć wiele sygnatur, zaś podczas kompilacji nie jesteśmy w stanie
ustalić, która z nich będzie właściwa. Przykładem takiej sytuacji są
kolekcje z heterogenicznymi elementami.
 Jeżeli x  Sygnatura, wówczas bag{x}  Sygnatura.
 Jeżeli x  Sygnatura, wówczas sequence{x}  Sygnatura.
 Zbiór Sygnatura nie ma innych elementów.
© K.Subieta. Podejście stosowe 13, Folia 23
Przykładowe sygnatury
Rezultaty zapytań
 struct{i1, i56}
 sequence{ i1, i6, i11}
 bag{struct{i1, i56}, struct{i6, i72},
struct{i11, i72}}
 bag{struct{n(„Kowalski”),
Zarobek(2500), d(i56)}}
 bag{struct{ Dział(i56),
Prac(bag{struct{n(„Nowak”), s(i9)},
struct{ n(„Stec” ), s(i14) }})}
© K.Subieta. Podejście stosowe 13, Folia 24
Odpowiadające im sygnatury
 struct{iPrac, iDział}
 sequence{ iPrac }
 bag{ struct{ iPrac, iDział } }
 bag{struct{n(string),
Zarobek(int), d(iDział)}}
 bag{struct{Dział(iDział),
Prac(bag{struct{n(string),s(iZar)}})
}}
Statyczna funkcja nested
 Analogicznie do funkcji nested, zdefiniujemy static_nested, której
zadaniem będzie przygotowanie sekcji na stosie S_ENVS w postaci
zbioru statycznych binderów. Funkcja static_nested działa na dowolnej
sygnaturze, ale jej wynik jest niepusty dla następujących przypadków:
• Dla sygnatury będącej referencją iNazwa do węzła grafu schematu opisującego
obiekt Nazwa rezultat static_nested zawiera wszystkie statyczne bindery
bytów podrzędnych. Np.
static_nested(iPrac) = { NrP(iNrp), Stan(iStan), Zar(iZar), PracujeW(iPracujeW),
Kieruje(iKieruje),ZmieńZar(iZmieńZar), ZarNetto(iZarNetto) }
• Dla sygnatury będącej referencją iNazwa do węzła grafu schematu opisującego
pointer Nazwa rezultat static_nested zawiera statyczny binder opisu obiektu,
do którego prowadzi ten pointer.
• Dla sygnatury będącej statycznym binderem static_nested zwraca zbiór
zawierający ten sam binder.
• Dla statycznych struktur:
static_nested(struct{s1, ... , sk}) = static_nested(s1)  ...  static_nested(sk)
© K.Subieta. Podejście stosowe 13, Folia 25
Drzewo syntaktyczne
 Drzewo syntaktyczne jest strukturą danych powstałą w wyniku rozbioru
gramatycznego (parsingu) zapytania.
 Zawiera węzły odpowiadające wszystkim semantycznie istotnym
elementom zapytania, powiązanym w taki sposób, aby całkowicie oddać
budowę zapytania, z pominięciem syntaktycznego lukru.
 Drzewo syntaktyczne może być bezpośrednio wejściem do interpretera
zapytań.
 Kontrola typologiczna zmienia drzewo syntaktyczne
 Później te zmiany wymusza optymalizacja zapytań
• Drzewo musi mieć strukturę ułatwiającą jego przekształcanie.
 Przepisywanie polega na przesuwaniu całych poddrzew w inne miejsce,
zmianie poddrzew, usuwaniu poddrzew lub uzupełnianiu drzewa o nowe
elementy.
© K.Subieta. Podejście stosowe 13, Folia 26
Przykład drzewa syntaktycznego
 Zapytanie: Emp.name union Dept.dname union “Doe”
Identyfikatory węzłów
potrzebne
do zmian drzewa oraz do
sygnalizacji błędów
Start
Algebraic2 union 1
L
R
Algebraic2 union 2
L
R
Non-algebraic .
3
Non-algebraic .
6
L
R
L
R
Name Emp 4
Name name 5
© K.Subieta. Podejście stosowe 13, Folia 27
string ”Doe” 9
Name Dept 7
Name dname 8
Zmiana drzewa syntaktycznego
 Kontrola typologiczna zmienia drzewo syntaktyczne zapytania
Start
Algebraic2 union 1
L
R
Algebraic2 union 2
L
R
string ”Doe” 9
Non-algebraic .
3
Non-algebraic .
6
L
R
L
R
Name Emp 4
© K.Subieta. Podejście stosowe 13, Folia 28
Algebraic1 tobag 12
Name Dept 7
Algebraic1 deref 10
Algebraic1 deref 11
Name name 5
Name dname 8
Reguły wnioskowania o typie
 Nie będziemy także zajmować się semantyką napisów, takich jak int, float,
string, bool, date itd.
• Matematycy widzą w takich napisach oznaczenia pewnych zbiorów, ale będzie
to dla nas nieistotne.
 Istotna będzie dla nas „arytmetyka” operatorów działających na takich
napisach, np.
•
•
•
•
•
(int + int)  int
(int + float)  float
(int = int)  bool
(int + string)  błąd typu  int
itd.
 Są to tzw. monomorficzne reguły wnioskowania o typie.
 Lewa strona takiej reguły przedstawia pewną sytuację podczas działania
procedury static_type_check, natomiast prawa strona - wynik tego działania.
 Elementami tej arytmetyki są sygnatury (wprowadzone poprzednio).
 Dla dowolnego operatora należy przypisać zestaw takich reguł.
© K.Subieta. Podejście stosowe 13, Folia 29