automatyczne dereferencje w języku sbql kazimierz subieta
DESCRIPTION
Automatyczne dereferencje w języku SBQL Kazimierz Subieta Polsko-Japońska Wyższa Szkoła Technik Komputerowych [email protected] Seminarium badawcze Katedry Inżynierii Oprogramowania PJWSTK 20 października 2011 r. Skąd wziął się problem?. - PowerPoint PPT PresentationTRANSCRIPT
K.Subieta: Automatyczne dereferencje w języku SBQL 1/21
Automatyczne dereferencje w języku SBQL Kazimierz SubietaPolsko-Japońska Wyższa Szkoła Technik [email protected]
Seminarium badawcze Katedry Inżynierii Oprogramowania PJWSTK20 października 2011 r.
K.Subieta: Automatyczne dereferencje w języku SBQL 2/21
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.
K.Subieta: Automatyczne dereferencje w języku SBQL 3/21
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.
K.Subieta: Automatyczne dereferencje w języku SBQL 4/21
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
Left subquery Right subquery
Name sal integer 1000
Start
Non-algebraic where
Left subquery Right subquery
Left subquery Right subquery
Name Emp Algebraic2 >
Name sal
Algebraic1 deref integer 1000
>
K.Subieta: Automatyczne dereferencje w języku SBQL 5/21
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.
K.Subieta: Automatyczne dereferencje w języku SBQL 6/21
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.
K.Subieta: Automatyczne dereferencje w języku SBQL 7/21
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….
K.Subieta: Automatyczne dereferencje w języku SBQL 8/21
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.
K.Subieta: Automatyczne dereferencje w języku SBQL 9/21
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]
K.Subieta: Automatyczne dereferencje w języku SBQL 10/21
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ć.
K.Subieta: Automatyczne dereferencje w języku SBQL 11/21
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
K.Subieta: Automatyczne dereferencje w języku SBQL 12/21
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.
K.Subieta: Automatyczne dereferencje w języku SBQL 13/21
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].
K.Subieta: Automatyczne dereferencje w języku SBQL 14/21
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.
K.Subieta: Automatyczne dereferencje w języku SBQL 15/21
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…
K.Subieta: Automatyczne dereferencje w języku SBQL 16/21
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]
Start
Algebraic2 union 1
L R
Algebraic2 union 2
L R
9string ”Doe”
Name dname 8
Non-algebraic . 3
L R
Name name 5
Name Emp 4
Non-algebraic . 6
L R
Name Dept 7
K.Subieta: Automatyczne dereferencje w języku SBQL 17/21
Skromny przykład (2)
• Procedura unifytypes is zastosowana dla pierwszego unionunifytypes(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ę:variant{iname[mutable=true, coll=bag, ASTnode=5], idname[mutable=true, coll=bag, ASTnode=8]}
[mutable=true, coll=bag, ASTnode=2]
K.Subieta: Automatyczne dereferencje w języku SBQL 18/21
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]
K.Subieta: Automatyczne dereferencje w języku SBQL 19/21
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.
K.Subieta: Automatyczne dereferencje w języku SBQL 20/21
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.
K.Subieta: Automatyczne dereferencje w języku SBQL 21/21
Na zakończenie…• 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?