Automatyczne dereferencje w języku SBQL

Slides:



Advertisements
Podobne prezentacje
Konstrukcja systemów obiektowych i rozproszonych
Advertisements

Język C/C++ Funkcje.
Podział i zastosowanie
Obiektowe języki zapytań
© K.Subieta. Obiektowe języki zapytań 08, Folia 1 kwiecień 2004 Obiektowe języki zapytań Wykładowca: Kazimierz Subieta Polsko-Japońska Wyższa Szkoła Technik.
Wykład 10 Metody Analizy Programów Specyfikacja Struktur Danych
© K.Subieta. Obiektowe języki zapytań 14, Folia 1 czerwiec 2004 Obiektowe języki zapytań Wykładowca: Kazimierz Subieta Polsko-Japońska Wyższa Szkoła Technik.
Bazy danych i inżynieria oprogramowania
Bazy danych i inżynieria oprogramowania
Wprowadzenie do C++ Zajęcia 2.
© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 3, Folia 1 październik 2004 Konstrukcja systemów obiektowych i rozproszonych Wykładowca:
Języki programowania C++
PROGRAMOWANIE STRUKTURALNE
Implementacja ekstensji klasy
© K.Subieta. Obiektowe języki zapytań 12, Folia 1 maj 2004 Obiektowe języki zapytań Wykładowca: Kazimierz Subieta Polsko-Japońska Wyższa Szkoła Technik.
© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 6, Folia 1 listopad 2004 Konstrukcja systemów obiektowych i rozproszonych Wykładowca: Kazimierz.
© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 7, Folia 1 listopad 2004 Konstrukcja systemów obiektowych i rozproszonych Wykładowca: Kazimierz.
© K.Subieta. Obiektowe języki zapytań 09, Folia 1 maj 2004 Obiektowe języki zapytań Wykładowca: Kazimierz Subieta Polsko-Japońska Wyższa Szkoła Technik.
© K.Subieta. Obiektowe języki zapytań 13, Folia 1 czerwiec 2004 Obiektowe języki zapytań Wykładowca: Kazimierz Subieta Polsko-Japońska Wyższa Szkoła Technik.
© K.Subieta. Obiektowe języki zapytań 07, Folia 1 kwiecień 2004 Obiektowe języki zapytań Wykładowca: Kazimierz Subieta Polsko-Japońska Wyższa Szkoła Technik.
Metoda pierwszeństwa operatorów
Domknięcie przechodnie (również) w bazach danych
Projektowanie systemów informacyjnych
Generyczne Repozytorium Dokumentów w XML
© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 8, Folia 1 listopad 2004 Konstrukcja systemów obiektowych i rozproszonych Wykładowca: Kazimierz.
© K.Subieta. Podejście stosowe 14, Folia 1 Podejście stosowe do obiektowych języków programowania baz danych Wykład 14 Mocna kontrola typów (2)
PySBQL Język zapytań dla obiektowych baz danych. Aplikacje bazodanowe Główny nurt budowania aplikacji opiera się na połączeniu: SQL JDBC Java Jak wyświetlić
ZŁOŻONOŚĆ OBLICZENIOWA
Materiały do zajęć z przedmiotu: Narzędzia i języki programowania Programowanie w języku PASCAL Część 7: Procedury i funkcje © Jan Kaczmarek.
Materiały do zajęć z przedmiotu: Narzędzia i języki programowania Programowanie w języku PASCAL Część 8: Wykorzystanie procedur i funkcji © Jan Kaczmarek.
Imperatywne modele obliczeń Copyright, 2001 © Jerzy R. Nawrocki Wprowadzenie do.
Imperatywne modele obliczeń Copyright, 2003 © Jerzy R. Nawrocki Teoretyczne podstawy.
Programowanie imperatywne i język C Copyright, 2004 © Jerzy R. Nawrocki Wprowadzenie.
Programowanie imperatywne i granice obliczalności Copyright, 2004 © Jerzy R. Nawrocki
Programowanie imperatywne i język C Copyright, 2004 © Jerzy R. Nawrocki Wprowadzenie.
Kurs Pascala – spis treści
INFORMATYKA Wykładowca: mgr Tadeusz Ziębakowski p. 126 I piętro (naprzeciw dziekanatu)
Wyrażenia Wyrażenie w Fortranie jest poprawną syntaktycznie kombinacją zmiennych, stałych, operatorów i funkcji. Wyrażenia są jednozdaniowymi przepisami.
Podprogramy.
Schemat Hornera Mgr inż. Michał Szucki.
Podejście stosowe do obiektowych języków programowania baz danych
Podstawy programowania II
Źródła: podręcznikopracował: A. Jędryczkowski.
Programowanie strukturalne i obiektowe
Języki i środowiska programowania systemów rozproszonych, Wykład 06, Slajd Języki i środowiska programowania systemów rozproszonych Wykładowca:
Języki i środowiska programowania systemów rozproszonych, Wykład 11, Slajd Języki i środowiska programowania systemów rozproszonych Wykładowca:
Języki i środowiska programowania systemów rozproszonych, Wykład 10, Slajd Języki i środowiska programowania systemów rozproszonych Wykładowca:
Języki i środowiska programowania systemów rozproszonych, Wykład 09, Slajd Języki i środowiska programowania systemów rozproszonych Wykładowca:
Języki i środowiska programowania systemów rozproszonych, Wykład 01 SBA&SBQL, Slajd Języki i środowiska programowania systemów rozproszonych Wykładowca:
Języki i środowiska programowania systemów rozproszonych, Wykład 07, Slajd Języki i środowiska programowania systemów rozproszonych Wykładowca:
Języki i środowiska programowania systemów rozproszonych, Wykład 12, Slajd Języki i środowiska programowania systemów rozproszonych Wykładowca:
Języki i środowiska programowania systemów rozproszonych, Wykład 01, Slajd Języki i środowiska programowania systemów rozproszonych Wykładowca:
Języki i środowiska programowania systemów rozproszonych, Wykład 05, Slajd Języki i środowiska programowania systemów rozproszonych Wykładowca:
C# Platforma .NET CZ.3 Kuba Ostrowski.
Rozwiązanie zadań do zaliczenia I0G1S4 // indeks
Podstawy informatyki 2013/2014
Wykład 10 typ zbiorowy rekurencja.
Plan prezentacji PJWSTK Motywacje powstania Cele projektu Podstawowe założenia Niezgodność impedancji Integracja składniowa Architektura rozwiązania.
Łukasz Bieszczad Mateusz Gałązka Karol Włodarek
Podsumowanie wiedzy MPDI2 sem.3 INFORMATYKA. tworzenie nowego pliku i katalogu, nawigacja po katalogach, listowanie zawartości katalogu, zmiana nazw,
PHP jest językiem skryptowym służącym do rozszerzania możliwości stron internetowych. Jego składnia jest bardzo podobna do popularnych języków programowania.
Wstęp do programowania Wykład 2 Dane, instrukcje, program.
Statyczna kontrola typów w SBQL Rafał Hryniów Polsko-Japońska Wyższa Szkoła Technik Komputerowych, Warszawa
K URS JĘZYKA C++ – WYKŁAD 3 ( ) Przenoszenie Składowe statyczne Funkcje wbudowane Argumenty domyślne.
P ASCAL Definicje, deklaracje, podstawowe instrukcje 1.
Obiektowe języki zapytań
Haskell Składnia funkcji.
Obiektowe języki zapytań
Zapis prezentacji:

Automatyczne dereferencje w języku SBQL Kazimierz Subieta Polsko-Japońska Wyższa Szkoła Technik Komputerowych subieta@pjwstk.edu.pl Seminarium badawcze Katedry Inżynierii Oprogramowania PJWSTK 20 października 2011 r.

Skąd wziął się problem? SBQL postawił znak równości pomiędzy zapytaniami i wyrażeniami języka programowania. Jest pierwszym językiem w historii informatyki, w którym zapytania są budulcem dla konstrukcji imperatywnych i abstrakcji języka programowania. Jego semantyka musi więc uwzględniać fakt, ze niektóre (pod) zapytania będą zwracały referencje, a nie wartości. Np. dla operatora podstawienia zapytanie z lewej strony operatora musi zwrócić referencję. Inny języki zapytań nie wspominają o referencjach. Semantyka i implementacja języka SBQL jest fundamentalnie oparta na przetwarzaniu referencji.

Niedobre podejście do problemu Programista wstawia funkcję deref wszędzie tam, gdzie chce zmienić referencję na wartość z nią skojarzoną: Zamiast pisać x + 5 powinien pisać deref(x) +5 Zamiast pisać Emp where sal > 1000 pisze Emp where deref(sal) > 1000 Taki styl byłby dla programistów bardzo irytujący. Funkcja deref została źle odebrana przez studentów zapoznających się z językiem SBQL. Stąd należy jej się pozbyć z kodu programu poprzez automatyczne jej wstawianie do drzew syntaktycznych zapytań podczas kontroli typologicznej. Najlepiej pozbyć się jej wszędzie, gdzie to jest możliwe.

Jak pozbyć się pisania deref? Podczas kontroli typologicznej, na podstawie sąsiedztwa z operatorem, następuje wniosek, że deref jest potrzebna: Następuje więc jej automatyczne wstawienie do AST. Np. dla zapytania Emp where sal >1000 Start Non - algebraic where Left subquery Right subquery Name Emp Algebraic2 sal integer 1000 > Algebraic1 deref >

Kiedy należy pozbyć się pisania deref? (1) Jeżeli sąsiadujący operator bezpośrednio wskazuje, że działa na wartościach, a nie na referencjach. Np. x + y posiada operator arytmetyczny + wskazujący, że argumentami powinny być wartości, zatem zmieniamy wyrażenie na deref(x) + deref(y). Wszystkie operatory arytmetyczne, stringowe, itd. Cecha zaimplementowana w systemie ODRA. Dla wyrażeń warunkowych: if exists(address) then address.city else “No address” Powinno być zamienione na: if exists(address) then deref(address.city) else “No address” Nie jest to zaimplementowane.

Kiedy należy pozbyć się pisania deref? (2) Jeżeli bag lub sekwencja (lub inna kolekcja) miesza referencje i wartości, to wszystkie wyrażenia zwracające referencje powinny być objęte funkcją deref: Np. bag(x, y, 5) powinien być zmieniony na bag(deref(x), deref(y), 5). Argument funkcji sum, avg, min, max zwracający referencję powinien być objęty funkcją deref. Jeżeli argumentem operacji na bagach lub sekwencjach jest kolekcja referencji, zaś drugim argumentem jest kolekcja wartości, to do zapytań zwracających referencje powinien by zastosowany deref.

Poszukiwanie generalnego przypadku Jest więcej takich przypadków. Problem jest rekurencyjny, wymagający generalnego podejścia. Sygnatury typów s1 i s2 mogą być typologicznie kompatybilne, ale różnić się wyłączcie tym, że w pewnym miejscu s1 zawiera wartość, zaś s2 zawiera referencję. To może zdarzyć się przy dowolnej złożoności s1 i s2, na dowolnym poziomie hierarchii zanurzenia sygnatur w sygnatury To zmusza do stosowania w ODRA funkcji deref eksplicite Problem wygląda na dość trudny w ogólnym przypadku. Szczęśliwie, znalazłem proste rozwiązanie … no może nie takie proste….

Przypomnienie: jak działa kontrola typów w SBQL Mechanizm symuluje rzeczywiste obliczenia podczas czasu kompilacji. Zamiast rzeczywistej bazy obiektów i stosów używa metabazy oraz statycznych stosów S_ENVS i S_QRES Symulacji dokonuje procedura static_eval, która działa prawie tak samo jak eval, ale nie przetwarza rzeczywistych obiektów Elementami przetwarzanymi na tych stosach są sygnatury, czyli typologiczne charakterystyki rezultatów zapytań. Sygnaturą może być typ atomowy (integer, string,…), identyfikator węzła metabazy, statyczny binder n(s), gdzie s jest sygnaturą, itd. Analogicznie do funkcji nested działa funkcja static_nested.

Suplementy (atrybuty) sygnatur Suplementy sygnatur przekazują dodatkową informację związaną z daną sygnaturą, taką jak: Mutowalność (zdolność do aktualizacji) Liczność (cardinality) informacja o potencjalnej liczność danej kolekcji, np. [0..*], [0..1], … Rodzaj kolekcji: element, bag, sequence, … Nazwa typu (dla nazwowej zgodności typów) …. parę innych da się jeszcze wymyśleć Każdy operator języka zapytań implikuje prostą arytmetykę suplementów sygnatur np. integer[mutable = true] + integer[mutable = true] = integer[mutable = false]

Gdzie jest problem? Jeżeli mamy operator  języka SBQL, który żąda unifikacji sygnatur (np. +, <, union, if,…), to mechanizm kontroli typów ma do czynienia z wyrażeniem s1  s2, gdzie s1 , s2 są sygnaturami argumentów operatora . Jeżeli s1 , s2 różnią się tym, że w pewnym miejscu jeden z nich zawiera typ atomowy t, a drugi identyfikator węzła metabazy typu t, to sygnatury są zgodne, ale przed wyrażenie zwracające id. węzła metabazy należy wstawić węzeł deref. Niestety, sygnatury nie zawierają informacji o tym, który fragment AST odpowiada za wygenerowanie tego identyfikatora. Wobec tego w ogólnym przypadku nie wiadomo gdzie deref wstawić.

No to rozwiązanie narzuca się samo… Trzeba do sygnatur dołożyć informację o węźle AST odpowiedzialnym za daną sygnaturę Tę informację wprowadzamy w postaci dodatkowego suplementu: Nazwałem go ASTnode. Wartością suplementu jest identyfikator węzła AST. Przykładowo: iname[mutable=true, coll=bag, ASTnode=5] sygnatura suplement mutable suplement rodzaj kolekcji suplement węzeł AST

Procedura unifytypes(s1, s2) Procedura unifytypes porównuje sygnatury s1 i s2 i zwraca wynikową sygnaturę dokonując unifikacji sygnatur s1 i s2 w pewną wynikową sygnaturę s. Dokonuje przy tym korekty AST poprzez wstawienie deref do odpowiedniego miejsca. Procedura sprawdza także typologiczną zgodność s1 i s2 ; jeżeli tej zgodności nie ma sygnalizuje błąd typologiczny. Następnie naprawia AST tak, aby kontrola typów mogła być kontynuowana. Procedura może być zastosowana we wszystkich przypadkach wymagających dereferencji, a także w innych przypadkach, np. zamiany elementu na bag.

Szkic procedury unifytypes (1) W pierwszym kroku procedura dokonuje serializacji sygnatur s1 i s2, tak aby mogły one być porównywane. Serializacja jest deterministyczna, np. poprzez sprowadzenie sygnatur do polskiej notacji. Sygnatury union compatible zawsze są serializowane w ten sam sposób. Każdy element struktury występujący w sygnaturach jest elementem serializacji, ale variant{v1, v2, …, vk} jest uważany za pojedynczy element serializacji. Po serializacji procedura obiega obie sygnatury w ten sam sposób i kolejności: dla i = 1,2,3,… porównuje s1[i] oraz s2[i].

Szkic procedury unifytypes (2) Błąd typologiczy jest sygnalizowany jeżeli s1[i] oraz s2[i] są typologicznie niezgodne. Błąd występuje jeżeli np. statyczne bindery mają różne nazwy, lub nie zgadzają się typy atomowe, lub liczność struktur jest różna. Następnie sygnatury są naprawiane i procedura jest kontynowana Dla automatycznych dereferencji istotny jest przypadek, kiedy w pewnym miejscu s1[i] ma wartość (nazwijmy ją a) zaś s2[i] jest identyfikatorem węzła metabazy (nazwijmy go r), przy czym typ r jest zgodny z a. W takim przypadku procedura korzysta z suplementu ASTnode przypisanego do s2[i] i wstawia przed ten węzeł funkcję deref.

Szkic procedury unifytypes (3) Analogicznie dla przypadku s1[i] = r i s2[i] = a Jeżeli s1[i] = r1, s2[i] = r2 to porównywane są typy siedzące pod r1 i r2 . Jeżeli są zgodne, to deref wstawia się zarówno przed ASTnode pobrane z s1[i] jak przed ASTnode pobrane z s2[i]. Jeżeli typy są niezgodne, to sygnalizuje się błąd i naprawia AST. Dalsze założenia dotyczą przypadku z wariantami. Szczegóły w nowym rozdziale książki, która się piszeeeeeeee…

Skromny przykład (1) Zapytanie: Emp.name union Dept.dname union “Doe” AST: Sygnatura Emp.name: iname[mutable=true, coll=bag, ASTnode = 5] Sygnatura Dept.dname: idname[mutable=true, coll=bag, ASTnode = 8] Sygnatura “Doe”: string[mutable=false, coll=null, ASTnode=9]

Skromny przykład (2) Procedura unifytypes is zastosowana dla pierwszego union unifytypes(iname[mutable=true, coll=bag, ASTnode=5], idname[mutable=true, coll=bag, ASTnode=8]) = variant{iname[mutable=true, coll=bag, ASTnode=5], idname[mutable=true, coll=bag, ASTnode=8]} static_eval zastosowany dla tego union zwróci sygnaturę: idname[mutable=true, coll=bag, ASTnode=8]} [mutable=true, coll=bag, ASTnode=2]

Skromny przykład (3) Drugi operator union implikuje następne zastosowanie procedury unifytypes: unifytypes(variant{iname[mutable=true, coll=bag, ASTnode=5], idname[mutable=true, coll=bag, ASTnode=8]} [mutable=true, coll=bag, ASTnode=2], string[mutable=false, coll=null, ASTnode=9]) = string[mutable=false, coll=bag] Procedura unifytypes wstawi węzły deref przed węzły ASTnode=5 i ASTnode=8. Zastosowanie drugiego union zwróci sygnaturę string[mutable=false, coll=bag, ASTnode=1]

Inne role ASTnode i unifytypes W ten sam sposób można dokonywać koercji pojedynczych elementów na bagi, sekwencji na bagi, itd. Identycznie z koercją integer na real i odwrotnie. Identycznie z rzutowanie obiektu na obiekt z klasy bardziej generalnej, np. Prac  Osoba Podobnie z rzutowaniem dynamicznej roli na jej nadrolę. Sygnalizacja błędów typologicznych: unifytypes potrafi zrobić to precyzyjniej, z dokładnością do węzła AST. Jeżeli w tym węźle będzie jeszcze informacja o koordynatach kodu źródłowego, który go wygenerował, to można łatwo przenieść sygnalizację na poziom kodu źródłowego, np. przez podświetlenie błędnego kodu.

Czy da się w ogóle usunąć deref z języka? Naszkicowana metoda pozwala uniknąć pisania deref eksplicite w większości przypadków. Nie da się jednak tego zrobić we wszystkich przypadkach bez obniżania mocy języka. Np. przy porównaniu q1 = q2 intencją programisty może być porównanie referencji lub porównanie wartości siedzących pod tymi referencjami Zatem potrzebny będzie kod deref( q1 ) = deref( q2 ) Podobnie z usuwaniem duplikatów. Można próbować to zastąpić jakimiś słowami kluczowymi, ale to wygląda na zamianę siekierki na kijek.

Na zakończenie… Pytania, komentarze, narzekania? Pozornie nieduży problem przerodził się w całkiem spory. Nie będzie łatwo zaimplementować go w ogólnym przypadku. Mogą być dalsze komplikacje związane z dereferencjami dla złożonych obiektów. Może trochę za mało tego na pracę doktorską, ale jeżeli problem byłby dostatecznie uogólniony, zaś implementacja powiązana z optymalizacjami, to kto wie… Dziękuję za uwagę. Pytania, komentarze, narzekania?