niedziela, 23 listopada 2008
SBQL AST Visualizer
Ostatecznie gramatyka wyszła mi taka:
Rule 1 query -> LPAREN query RPAREN
Rule 2 query -> LITERAL
Rule 3 query -> NUMBERLITERAL
Rule 4 query -> STRINGLITERAL
Rule 5 query -> UNARYOP query
Rule 6 query -> query SIMPLEBINARYOP query
Rule 7 query -> query DOT query
Rule 8 query -> query COMMA query
Rule 9 query -> query AS query
Rule 10 query -> query JOIN query
Rule 11 query -> query WHERE query
Rule 12 query -> query AND query
Rule 13 query -> query OR query
z kolejnością wiąząń:
precedence = (
('left', 'WHERE', 'JOIN') ,
('left', 'AND', 'OR'),
('left', 'SIMPLEBINARYOP'),
('left', 'AS', 'DOT')
)
na końcu pliku są takie przykłady:
data = {
"01simple": "(2+2 < 4) and 1",
"02projection" : '(Employee where salary < 200).(name, surname)',
"03more" :'(Employee where surname = "Kowalski" and salary < 200).name',
"04MappedJoin" : 'Employee.worksIn.Dept',
"05forjoin" : '(Employee where surname = "Kowalski" and worksIn.Departmet.isLocatedIn.Location.name = "Lodz").(surname, birthdate)',
"06join" : '(Employee as e join e.worksIn.Department as d join d.isLocatedIn.Location as l).(e.surname, l.name)',
"07join2" : '(Employee where surname = "Kowalski" and worksIn.Department.name = "Production").(surname, birthdate)'
}
niedziela, 19 października 2008
Home cooking: metaprogramming a'la Python
Metaprogramowanie to najprościej rzecz ujmując pisanie programów, które piszą programy. Lekki wstęp można znaleźć tutaj wikipedia:Metaprogramming, a całą koncepcję najłatwiej wyjaśnić na przykładzie LISPA, w którym program piszę się bezpośrednio w drzewie składniowym a kod programu jest listą. Zatem przy niewielkiej zmianie w syntaktyce można stworzyć konstrukcje (tutaj: makro), które w momencie uruchomienia generuje inną listę i ją wywołuję jako program.
No dobra, ale po co to wszystko? Okazuje się, że to bardzo potężny mechanizm, a Paul Graham twierdzi, że jego programy w LISP były złożone w około 40% z makr, co pozwalało mu tworzyć web-dwa-zero projekt (który został ostatecznie wykupiony przez Yahoo) znacznie szybciej niż jego ówczesna konkurencja.
No wielkim zaskoczeniem nie będzie, że metaprogramowanie zostało dorzucone również do Pythona, a konstrukcja, która na to pozwala to Metaclasses. Na sam początek:
Metaclasses are deeper magic than 99% of users should ever worry about. If you wonder whether you need them, you don't (the people who actually need them know with certainty that they need them, and don't need an explanation about why). -- Tim Peters
A więc motywacje już mamy (!)
Na początek problem: Stworzyć interpreter zapytań podobnych do tych tutaj sbql:examples. Dodatkowo niech program nie będzie dłuższy niż cztery ekrany. Oczywiście podobieństwo naszych zapytań do zapytań języka SBQL jest mocno naciągane, niemniej jednak przyjrzyjmy się:
class Osoba():
__metaclass__ = pql_memorystore
imie = Attribute(str, "[*..2]")
nazwisko = Attribute(type = str, card = "[1..1]")
wiek = Attribute(int)
def __init__(self, imie, nazwisko):
self.imie = imie
self.nazwisko = nazwisko
w drugiej linijce określamy tylko metaklasę dla naszej, klasy co sprawia, że nasza żmudnie tworzona klasa Osoba po zakończeniu jej definicji staje sie już zupełnie czymś innym. A w naszym przypadku będzie listą. Czyli mamy klasę, która jest jednocześnie listą i dodatkowo każda nowa instancja tej klasy odkłada się do siebie... weird kind of magic
hmmm sprawdźmy:
Możemy zatem tworzyć obiekty:
o1 = Osoba(imie = "Adam", nazwisko = "Janskowski")
o2 = Osoba(imie = "Janek", nazwisko = "Wlodarczyk")
Osoba("Sigmun", "Freud")
Osoba(imie = "Adam", nazwisko = "Malysz")
Osoba("Tolek", "Skoczylas")
i wykonywać na nich coś w rodzaju zapytań, które operują na instancjach własnych klas:
Osoba
Osoba.imie
[o for o in Osoba if o.imie == ['Adam']]
pql_list([o for o in Osoba if o.imie == ['Adam']]).Nazwisko
Pewnie podobieństwo do SBQL można by jeszcze trochę podciągnąć w ramach samego Pythona przeciążając operatory; znacznie więcej dałoby rade pewnie podciągnąć pewnie evalem, ale przecież to nie o to chodziło.
Program jest tutaj. Napisałem go dawno temu (w czasach gdy jeszcze pterodaktyle latały po niebie) i nigdy nie skończyłem ale w sumie mniej więcej działa, a w pliku jest więcej przykładów. Jest tam nawet wstęp do stworzenia kontroli typów i kardynalności atrybutów.