Metody Realizacji Języków Programowania

Podobne dokumenty
Metody Realizacji Języków Programowania

4 Literatura. c Dr inż. Ignacy Pardyka (Inf.UJK) ASK MP.01 Rok akad. 2011/ / 24

Wykład 14. Środowisko przetwarzania

Kurs programowania. Wstęp - wykład 0. Wojciech Macyna. 22 lutego 2016

Programowanie Niskopoziomowe

Przydział pamięci. Teoria kompilacji. Dr inż. Janusz Majewski Katedra Informatyki

14. Elementy systemu wykonawczego

Instrukcja do ćwiczenia P4 Analiza semantyczna i generowanie kodu Język: Ada

Programowanie Niskopoziomowe

Metody Realizacji Języków Programowania

Wykład 8: klasy cz. 4

Uwagi dotyczące notacji kodu! Moduły. Struktura modułu. Procedury. Opcje modułu (niektóre)

Wstęp do programowania. Procedury i funkcje. Piotr Chrząstowski-Wachtel

Dynamiczny przydział pamięci w języku C. Dynamiczne struktury danych. dr inż. Jarosław Forenc. Metoda 1 (wektor N M-elementowy)

Informatyka I. Klasy i obiekty. Podstawy programowania obiektowego. dr inż. Andrzej Czerepicki. Politechnika Warszawska Wydział Transportu 2018

Podstawy programowania. Wykład: 12. Struktury, unie, pola bitowe. dr Artur Bartoszewski -Podstawy programowania, sem 1 - WYKŁAD

Programowanie obiektowe

Dziedziczenie. Streszczenie Celem wykładu jest omówienie tematyki dziedziczenia klas. Czas wykładu 45 minut.

Programowanie obiektowe - 1.

1. Które składowe klasa posiada zawsze, niezależnie od tego czy je zdefiniujemy, czy nie?

Wykład 4: Klasy i Metody

Programowanie obiektowe


Referencje do zmiennych i obiektów

1. Nagłówek funkcji: int funkcja(void); wskazuje na to, że ta funkcja. 2. Schemat blokowy przedstawia algorytm obliczania

Paradygmaty programowania

Programowanie obiektowe

Programowanie niskopoziomowe

Obliczenia na stosie. Wykład 9. Obliczenia na stosie. J. Cichoń, P. Kobylański Wstęp do Informatyki i Programowania 266 / 303

Wstęp do programowania. Drzewa podstawowe techniki. Piotr Chrząstowski-Wachtel

< K (2) = ( Adams, John ), P (2) = adres bloku 2 > < K (1) = ( Aaron, Ed ), P (1) = adres bloku 1 >

Wykład 9: Polimorfizm i klasy wirtualne

Wykład 5: Klasy cz. 3

C++ - przeciążanie operatorów. C++ - przeciążanie operatorów. C++ - przeciążanie operatorów. C++ - przeciążanie operatorów

wykład Organizacja plików Opracował: dr inż. Janusz DUDCZYK

Dziedziczenie. Tomasz Borzyszkowski

Programowanie Obiektowe i C++

Języki i techniki programowania Ćwiczenia 2

kiedy znowu uzyska sterowanie, to podejmuje obliczenie od miejsca, w którym poprzednio przerwała, i z dotychczasowymi wartościami zmiennych,

Metody Realizacji Języków Programowania

C++ - polimorfizm. C++ - polimorfizm. C++ - polimorfizm. C++ - polimorfizm. C++ - polimorfizm POLIMORFIZM

Podstawy programowania. Wykład PASCAL. Zmienne wskaźnikowe i dynamiczne. dr Artur Bartoszewski - Podstawy prograowania, sem.

Wstęp do programowania

Ada-95. Dariusz Wawrzyniak

PROE wykład 2 operacje na wskaźnikach. dr inż. Jacek Naruniec

znajdowały się różne instrukcje) to tak naprawdę definicja funkcji main.

Programowanie Obiektowe i C++

Materiały do laboratorium MS ACCESS BASIC

Programowanie Obiektowe i C++

Programowanie obiektowe Wykład 6. Dariusz Wardowski. dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/14

C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy WSKAŹNIKI KLASOWE

JĘZYKI PROGRAMOWANIA Z PROGRAMOWANIEM OBIEKTOWYM. Wykład 6

Obszar statyczny dane dostępne w dowolnym momencie podczas pracy programu (wprowadzone słowem kluczowym static),

PROGRAMOWANIE NISKOPOZIOMOWE. Adresowanie pośrednie rejestrowe. Stos PN.04. c Dr inż. Ignacy Pardyka. Rok akad. 2011/2012

Metody Kompilacji Wykład 3

Podstawy programowania. Wykład Funkcje. Krzysztof Banaś Podstawy programowania 1

JAVA W SUPER EXPRESOWEJ PIGUŁCE

Ćwiczenie nr 6. Programowanie mieszane

Uniwersytet Zielonogórski Instytut Sterowania i Systemów Informatycznych. Ćwiczenie 3 stos Laboratorium Metod i Języków Programowania

Dariusz Brzeziński. Politechnika Poznańska, Instytut Informatyki

zmienne stanowią abstrakcję komórek pamięci: programista może przechowywać dane w pamięci, nie martwiąc się o techniczne szczegóły (np.

Programowanie obiektowe Wykład 3. Dariusz Wardowski. dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/21

Typy klasowe (klasy) 1. Programowanie obiektowe. 2. Założenia paradygmatu obiektowego:

Podstawy Informatyki. Metody dostępu do danych

Programowanie obiektowe

Podstawy programowania. Wykład: 7. Funkcje Przekazywanie argumentów do funkcji. dr Artur Bartoszewski -Podstawy programowania, sem 1 - WYKŁAD

TEMAT : KLASY DZIEDZICZENIE

Programowanie w C++ Wykład 5. Katarzyna Grzelak. 26 marca kwietnia K.Grzelak (Wykład 1) Programowanie w C++ 1 / 40

Pakiety i interfejsy. Tomasz Borzyszkowski

Programowanie Obiektowe i C++ Marcin Benke

Podstawy programowania komputerów

Zmienne, stałe i operatory

PHP 5 język obiektowy

ZASADY PROGRAMOWANIA KOMPUTERÓW

Ćwiczenie 3. Konwersja liczb binarnych

Laboratorium z przedmiotu Programowanie obiektowe - zestaw 04

Projektowanie obiektowe. Roman Simiński Polimorfizm

Wstęp do programowania 2

Diagramy klas. dr Jarosław Skaruz

Tadeusz Pankowski

Enkapsulacja, dziedziczenie, polimorfizm

Podstawy programowania. Wykład 7 Tablice wielowymiarowe, SOA, AOS, itp. Krzysztof Banaś Podstawy programowania 1

Programowanie Obiektowe i C++

PROGRAMOWANIE NISKOPOZIOMOWE. Struktury w C. Przykład struktury PN.06. c Dr inż. Ignacy Pardyka. Rok akad. 2011/2012

Kurs programowania. Wykład 2. Wojciech Macyna. 17 marca 2016

Podstawy programowania 2. Temat: Drzewa binarne. Przygotował: mgr inż. Tomasz Michno

Podstawy Programowania Obiektowego

Architektura komputerów

Java - tablice, konstruktory, dziedziczenie i hermetyzacja

Kurs rozszerzony języka Python

Języki programowania C i C++ Wykład: Typy zmiennych c.d. Operatory Funkcje. dr Artur Bartoszewski - Języki C i C++, sem.

Praktycznie całe zamieszanie dotyczące konwencji wywoływania funkcji kręci się w okół wskaźnika stosu.

Techniki programowania INP001002Wl rok akademicki 2018/19 semestr letni. Wykład 3. Karol Tarnowski A-1 p.

Pola i metody statyczne

10. Translacja sterowana składnią i YACC

Mechanizm dziedziczenia

Procesor ma architekturę rejestrową L/S. Wskaż rozkazy spoza listy tego procesora. bgt Rx, Ry, offset nand Rx, Ry, A add Rx, #1, Rz store Rx, [Rz]

Język programowania: Lista instrukcji (IL Instruction List)

PLAN WYKŁADU BAZY DANYCH INDEKSY - DEFINICJE. Indeksy jednopoziomowe Indeksy wielopoziomowe Indeksy z użyciem B-drzew i B + -drzew

Podstawy programowania obiektowego

Transkrypt:

Metody Realizacji Języków Programowania Realizacja funkcji, procedur i metod Marcin Benke MIM UW 6 grudnia 2010 Marcin Benke (MIM UW) Metody Realizacji Języków Programowania 6 grudnia 2010 1 / 1

Realizacja funkcji i procedur Instrukcja wywołania funkcji nakazuje rozpoczęcie wykonania funkcji, a po jej zakończeniu powrót do instrukcji za wywołaniem. Historię obliczeń w programie można przedstawić w postaci tzw. drzewa aktywacji, którego węzły reprezentuja wcielenia (wykonania) funkcji. Marcin Benke (MIM UW) Metody Realizacji Języków Programowania 6 grudnia 2010 2 / 1

Drzewo aktywacji Korzeń tego drzewa to wykonanie programu głównego a węzeł F ma synów G 1... G n jeśli wcielenie funkcji F wywołało G 1, później G 2 itd. Podczas wykonania programu odwiedzamy węzły porzadku prefiksowym, od lewej do prawej. Na ścieżce od korzenia do aktualnego węzła sa aktywne wcielenia funkcji, na lewo już zakończone a na prawo jeszcze się nie rozpoczęte. Jeśli istnieje ścieżka, na której występuje wiele wcieleń tej samej funkcji, mówimy że funkcja ta jest rekurencyjna. Marcin Benke (MIM UW) Metody Realizacji Języków Programowania 6 grudnia 2010 3 / 1

Przekazywanie sterowania Sa dwa sposoby realizacji przekazywania sterowania między wołajacym a wołanym: podprogram otwarty (ang. inline, macro): kod funkcji/procedury wołanej wstawiamy w miejscu wywołania podprogram zamknięty: przekazanie sterowania następuje za pomoca instrukcji skoku ze śladem Podprogram otwarty może dać bardziej efektywny kod eliminuje instrukcje skoku. W większości przypadków wydłużenie kodu wynikowego, mniej uniwersalna metoda nie można jej zastosować do funkcji rekurencyjnych. W dalszej części wykładu zajmiemy się podprogramami zamkniętymi. Marcin Benke (MIM UW) Metody Realizacji Języków Programowania 6 grudnia 2010 4 / 1

Rekord aktywacji Z każdym wcieleniem funkcji wiażemy pewne informacje. Obszar pamięci, w którym sa zapisywane, nazywamy rekordem aktywacji albo ramka (ang. frame). W większości języków potrzebne sa tylko rekordy dla aktywnych wcieleń na aktualnej ścieżce w drzewie aktywacji. Gdyby nie rekurencja, dla każdej funkcji moglibyśmy z góry zarezerwować obszar pamięci na jeden rekord aktywacji, gdyż wiemy, że tylko tyle rekordów będzie potrzebnych (patrz wczesny Fortran). W językach z rekurencja rekordy aktywacji alokujemy przy wywołaniu funkcji a zwalniamy, gdy funkcja się skończy. Rekordy aktywacji przechowujemy więc na stosie. Marcin Benke (MIM UW) Metody Realizacji Języków Programowania 6 grudnia 2010 5 / 1

Zawartość rekordu aktywacji Informacje pamiętane w rekordzie aktywacji zależa m. in. od języka. Moga tam być: parametry zmienne lokalne i zmienne tymczasowe ślad powrotu kopia rejestrów (wszystkich, niektórych lub żadnego) łacze dynamiczne (DL, ang. dynamic link) wskaźnik na poprzedni rekord aktywacji; ciag rekordów połaczonych wskaźnikami DL tworzy tzw. łańcuch dynamiczny. łacze statyczne (SL, ang. static link) miejsce na wynik Postać rekordu aktywacji nie jest sztywno określona projektuje ja autor implementacji języka. Marcin Benke (MIM UW) Metody Realizacji Języków Programowania 6 grudnia 2010 6 / 1

Adresowanie rekordu aktywacji Adres ramki jest zwykle przechowywany w wybranym rejestrze (FP = frame pointer, BP = base pointer). Pola rekordu aktywacji sa adresowane przez określenie ich przesunięcia względem adresu w FP. Każde wcielenie funkcji, niezależnie od połozenia rekordu aktywacji, w ten sam sposób może korzystać z jego zawartości, a więc wszystkie wcielenia maja wspólny kod. Adresem rekordu aktywacji nie musi być adres jego poczatku. Jeśli uznamy, że tak będzie wygodniej, możemy przyjać, że adresem rekordu aktywacji będzie adres jednego z pól w środku tego rekordu. Marcin Benke (MIM UW) Metody Realizacji Języków Programowania 6 grudnia 2010 7 / 1

Adresowanie rekordu aktywacji Jeśli w języku występuja funkcje ze zmienna liczba argumentów (jak np. w C), adresowanie rekordu aktywacji względem jego środka może być najwygodniejszym rozwiazaniem. Gdyby pola rekordu aktywacji były adresowane względem jego poczatku, przesunięcia pól zależałyby od liczby parametrów, a więc nie byłyby znane podczas kompilacji. Rozwiazaniem tego problemu jest adresowanie rekordu aktywacji względem miejsca pomiędzy parametrami a zmiennymi lokalnymi funkcji. Parametry wkłada się do rekordu aktywacji w kolejności od ostatniego do pierwszego, dzięki czemu przesunięcie miejsca, w którym znajduje się K-ty parametr, nie zależy od liczby parametrów, tylko od stałej K. Wynik funkcji często w rejestrach zamiast na stosie. Marcin Benke (MIM UW) Metody Realizacji Języków Programowania 6 grudnia 2010 8 / 1

Pomijanie wskaźnika ramki Aktualny rekord aktywacji zawsze znajduje się na wierzchołku stosu rekordów aktywacji; można do jego adresowania uzyć wskaźnika stosu. Zalety: oszczędzamy jeden rejestr i kilka instrukcji na każde wywołanie. Wady: wierzchołek stosu przesuwa się podczas obliczeń, powodujac zmiany przesunięć pól rekordu aktywacji; podatne na błędy w generowaniu kodu. Rozwiazanie stosowane w JVM, także w GCC z opcja -fomit-frame-pointer (zatem przeważnie także z opcja -O) Marcin Benke (MIM UW) Metody Realizacji Języków Programowania 6 grudnia 2010 9 / 1

Protokół wywołania (i powrotu z) funkcji Protokół wywołania opisuje czynności, które ma wykonać wołajacy (zarówno przed przekazaniem sterowania do wołanego, jak i po powrocie) oraz to, co wołany (czyli każda funkcja) ma robić na poczatku i na końcu. Podstawowym zadaniem jest zbudowanie rekordu aktywacji oraz usunięcie go. Niektóre czynności musi wykonywać wołajacy (np. liczenie parametrów), inne wołany (np. zarezerwowanie miejsca na zmienne lokalne), a jeszcze inne może wykonać zarówno wołany jak i wołajacy. Marcin Benke (MIM UW) Metody Realizacji Języków Programowania 6 grudnia 2010 10 / 1

Protokół wywołania (i powrotu z) funkcji Zaprojektujemy protokół wywołania i powrotu z funkcji. Założymy przy tym następujac a postać rekordu aktywacji: miejsce na wynik parametry ślad DL zmienne Marcin Benke (MIM UW) Metody Realizacji Języków Programowania 6 grudnia 2010 11 / 1

Protokół wywołania (i powrotu z) funkcji Wskaźnikiem rekordu aktywacji będzie BP zawierajacy adres pola DL. wołajacy PUSH 0 ; miejsce na wynik <parametry na stos> CALL adres_wołanego ADD n, SP ; n - łączny rozmiar parametrów ; wynik zostaje na stosie wołany PUSH BP ; DL na stos MOV SP, BP ; aktualizacja wskaźnika ramki SUB k, SP ; k - łączny rozmiar zmiennych... ; tłumaczenie treści funkcji MOV BP, SP ; przywracamy wskaźnik stosu POP BP ; przywracamy wskaźnik ramki RET ; powrót do wołającego Marcin Benke (MIM UW) Metody Realizacji Języków Programowania 6 grudnia 2010 12 / 1

Przykład int sumto(int n) { int i, sum; i = 0; sum = 0; while (i<n) { i = i+1; sum = sum+i; } return sum; } Marcin Benke (MIM UW) Metody Realizacji Języków Programowania 6 grudnia 2010 13 / 1

Z ramka stosu sumto: pushl %ebp movl %esp, %ebp subl $8, %esp movl $0, -8(%ebp) ; i movl $0, -4(%ebp) ; sum jmp.l2.l3: addl $1, -8(%ebp) movl -8(%ebp), %eax addl %eax, -4(%ebp).L2: movl 8(%ebp), %eax ; n cmpl %eax, -8(%ebp) jl.l3 movl -4(%ebp), %eax leave ; = movl ebp, esp; popl ebp ret Marcin Benke (MIM UW) Metody Realizacji Języków Programowania 6 grudnia 2010 14 / 1

Bez ramki stosu sumto:.l5:.l4: movl 4(%esp), %ecx ; ecx = n xorl %eax, %eax ; eax = 0 testl %ecx, %ecx ; ecx <=0? jle.l4 ; skok do L4 xorl %edx, %edx ; edx = 0 addl $1,%edx ; edx += 1 addl %edx, %eax ; eax += eax cmpl %edx, %ecx ; edx!= n? jne.l5 ; skok do L5 ret ; powrót Marcin Benke (MIM UW) Metody Realizacji Języków Programowania 6 grudnia 2010 15 / 1

Interludium: maszyna stosowa W dalszym ciagu wykładu będziemy się posługiwać prosta maszyna stosowa, z operacjami: stała połóż stała na stosie LOAD połóż na stosie wartość spod adresu zdjętego ze stosu STORE zdejmuje ze stosu adres, następnie zdejmuje ze stosu wartość i wkłada ja pod ten adres ADD, SUB,... zdejmuje ze stosu argumenty i zastępuje wynikiem operacji GOTO skacze pod adres na stosie CALL j.w, zostawiajac na stosie ślad powrotu SP kładzie na stosie adres wskaźnika stosu FP kładzie na stosie adres wskaźnika ramki Marcin Benke (MIM UW) Metody Realizacji Języków Programowania 6 grudnia 2010 16 / 1

Mechanizm przekazywania parametrów Dwa najczęściej spotykane tryby przekazywania parametrów to: przekazywanie parametru przez wartość: wołajacy umieszcza w rekordzie aktywacji wartość argumentu; wołany może odczytać otrzymana wartość oraz, jeśli język programowania na to pozwala, zmieniać ja traktujac parametr tak samo, jak zmienna lokalna; ewentualne zmiany nie sa widziane przez wołajacego. przekazywanie parametru przez zmienna (referencję) wołajacy umieszcza w rekordzie aktywacji adres zmiennej; wołany może odczytać wartość argumentu sięgajac pod ten adres, może też pod ten adres coś wpisać, zmieniajac tym samym wartość zmiennej będacej argumentem. Marcin Benke (MIM UW) Metody Realizacji Języków Programowania 6 grudnia 2010 17 / 1

Przykład 1 W programie, którego fragment wyglada następujaco: procedure p; var a,b : integer; begin a := q(b,b) end; function q(x : integer; var y : integer) : integer; var z : integer; begin q := x + y; y := 7 end; Marcin Benke (MIM UW) Metody Realizacji Języków Programowania 6 grudnia 2010 18 / 1

rekord aktywacji procedury p wygladałby tak (w nawiasach podano przesunięcia poszczególnych pól względem pola DL wskazywanego przez rejestr FP): ( 2 ) miejsce na wynik ( 1 ) ślad ( 0 ) DL ( -1 ) a ( -2 ) b a rekord aktywacji funkcji q tak: ( 4 ) miejsce na wynik ( 3 ) x ( 2 ) y ( 1 ) ślad ( 0 ) DL ( -1 ) z Marcin Benke (MIM UW) Metody Realizacji Języków Programowania 6 grudnia 2010 19 / 1

kod wynikowy dla procedury p miałby postać: FP LOAD ; DL do ramki SP LOAD FP STORE ; nowy adres ramki do FP 0 0 ; miejsce na dwie zmienne 0 ; miejsce na wynik FP LOAD -2 ADD LOAD ; wartość b FP LOAD -2 ADD ; adres zmiennej b q CALL ; skok ze śladem do q DROP DROP ; usuwamy parametry FP LOAD -1 ADD STORE ; przypisujemy wynik na a DROP DROP ; usuwamy zmienne FP STORE ; wracamy do poprzedniej ramki GOTO ; i do miejsca wywołania Marcin Benke (MIM UW) Metody Realizacji Języków Programowania 6 grudnia 2010 20 / 1

a kod funkcji q: FP LOAD ; DL do ramki SP LOAD FP STORE ; nowy adres ramki do FP 0 ; miejsce na jedną zmienną FP LOAD 3 ADD LOAD ; wartość x na stos FP LOAD 2 ADD LOAD LOAD ; wartość y na stos ADD ; dodajemy x i y FP LOAD 4 ADD ; adres miejsca na wynik STORE ; zapamiętujemy wynik 7 ; stała na stos FP LOAD 2 ADD LOAD ; adres zmiennej ; przekazanej jako y STORE ; przypisanie na y DROP ; usuwamy zmienną FP STORE ; wracamy do poprzedniej ramki GOTO ; i do miejsca wywołania Marcin Benke (MIM UW) Metody Realizacji Języków Programowania 6 grudnia 2010 21 / 1

Środowisko w językach ze struktura blokowa Wiele języków programowania (n.p. Pascal) pozwala na zagnieżdżanie funkcji i procedur. Języki te nazywamy językami ze struktura blokowa. Kod funkcji ma dostęp nie tylko do jej danych lokalnych, ale także do danych funkcji, w której jest zagnieżdżona itd. aż do poziomu globalnego. Działanie funkcji jest określone nie tylko przez jej kod oraz parametry, lecz także przez środowisko, w którym ma się wykonać. Marcin Benke (MIM UW) Metody Realizacji Języków Programowania 6 grudnia 2010 22 / 1

Wiazanie statyczne i dynamiczne Postać środowiska jest w Pascalu wyznaczona statycznie z kodu programu wynika, do której funkcji należy rekord aktywacji, w którym mamy szukać zmiennej nielokalnej. Mówimy, że w Pascalu obowiazuje statyczne wiazanie zmiennych. Istnieja również języki (n.p. Lisp), w których obowiazuje wiazanie dynamiczne w przypadku odwołania do danej nielokalnej, szukamy jej w rekordzie aktywacji wołajacego itd. w górę po łańcuchu dynamicznym. Marcin Benke (MIM UW) Metody Realizacji Języków Programowania 6 grudnia 2010 23 / 1

Łacze statyczne By korzystać z danych nielokalnych, działajaca funkcja musi mieć dostęp do swojego środowiska. Moglibyśmy przekazać jej wszystkie dane znajdujace się w jej środowisku jako dodatkowe parametry. Rozwiazanie takie stosuje się często w językach funkcyjnych. W językach imperatywnych najczęściej stosowanym rozwiazaniem jest powiazanie w listę ciagu ramek, które sa na ścieżce w hierarchii zagnieżdżania. Każda ramka zawiera łacze statyczne (SL, static link) wskaźnik do jednego z rekordów aktywacji funkcji otaczajacej dana. Rekord ten nazywamy poprzednikiem statycznym, a ciag rekordów połaczonych SL to łańcuch statyczny. Marcin Benke (MIM UW) Metody Realizacji Języków Programowania 6 grudnia 2010 24 / 1

Wyliczanie SL SL musi być liczony przez wołajacego, bo do jego określenia trzeba znać zarówno funkcję wołana jak i wołajac a. Środowisko dla funkcji wołanej zależy od środowiska wołajacej jeśli obie widza zmienna x, jej wartość ma być dla nich równa. Jeśli funkcja F znajdujaca się na poziomie zagnieżdżenia F p wywołuje G z poziomu zagnieżdżenia G p, w pole SL wpisze adres rekordu, który odnajdzie przechodzac po własnym łańcuchu statycznym o F p G p + 1 kroków w górę. Jeśli np. G jest funkcja lokalna F (czyli G p = F p + 1), funkcja F w pole SL dla G wpisze adres swojego rekordu; jeśli F i G sa na tym samym poziomie zagnieżdżenia, w polu SL dla G będzie to, co w SL dla F itd. Marcin Benke (MIM UW) Metody Realizacji Języków Programowania 6 grudnia 2010 25 / 1

Dostęp do danych nielokalnych Dane lokalne funkcji sa w jej rekordzie aktywacji a dane globalne w ustalonym miejscu w pamięci można do nich sięgać za pomoca adresów bezwzględnych. Z danych, które nie sa ani lokalne ani globalne, korzystamy przy pomocy łańcucha statycznego. W funkcji F o poziomie F p sięgamy do zmiennej z funkcji G o poziomie G p (oczywiście F p G p ), przechodzac po łańcuchu statycznym F p G p kroków w górę. Tam pod przesunięciem znanym podczas kompilacji jest nasza zmienna. Adres zmiennej jest wyznaczony przez poziom zagnieżdżenia i przesunięcie w rekordzie. Adresy rekordów z łańcucha statycznego można też wpisać do tablicy (tzw. display). Dzięki temu unikniemy chodzenia po łańcuchu statycznym, ale za to trzeba będzie stale aktualizować tablicę. Marcin Benke (MIM UW) Metody Realizacji Języków Programowania 6 grudnia 2010 26 / 1

Przykład 2 Przyjmijmy, że w rekordzie aktywacji SL będzie się znajdował pomiędzy parametrami a śladem powrotu. Zakładamy też, że protokół wywołania i powrotu z funkcji jest prawie taki sam, jak w poprzednim przykładzie. Jedyna różnica będzie dodanie po stronie wołajacego obliczenia SL przed wywołaniem i usunięcia go ze stosu po powrocie sterowania. Marcin Benke (MIM UW) Metody Realizacji Języków Programowania 6 grudnia 2010 27 / 1

Przykład 2 W programie, którego fragment wyglada następujaco: procedure p; var a : integer; procedure q; var b : integer; procedure r; var c : integer; procedure s; begin... end {s}; begin a:=b+c; s; q end {r}; begin... end {q}; begin... end {p}; Marcin Benke (MIM UW) Metody Realizacji Języków Programowania 6 grudnia 2010 28 / 1

Przykład 2 rekord aktywacji p rekord aktywacji procedury p wygladałby tak (w nawiasach podano przesunięcia poszczególnych pól względem pola DL wskazywanego przez rejestr FP): ( 3 ) miejsce na wynik ( 2 ) SL ( 1 ) ślad ( 0 ) DL ( -1 ) a Marcin Benke (MIM UW) Metody Realizacji Języków Programowania 6 grudnia 2010 29 / 1

Przykład 2 rekordy aktywacji q,r procedury q tak: ( 3 ) miejsce na wynik ( 2 ) SL ( 1 ) ślad ( 0 ) DL ( -1 ) b a procedury r tak: ( 3 ) miejsce na wynik ( 2 ) SL ( 1 ) ślad ( 0 ) DL ( -1 ) c Marcin Benke (MIM UW) Metody Realizacji Języków Programowania 6 grudnia 2010 30 / 1

Przykład 2 kod procedury r kod wynikowy dla procedury r miałby postać: r: FP LOAD ; DL do rekordu aktywacji SP LOAD FP STORE ; nowy adres ramki do FP 0 ; miejsce na zmienną c FP LOAD 2 ADD LOAD ; SL na stos -1 ADD LOAD ; wartość b na stos FP LOAD -1 ADD LOAD ; wartość c na stos ADD ; b+c na stos FP LOAD 2 ADD LOAD ; SL na STOS 2 ADD LOAD ; na stos adres ramki p -1 ADD ; na stos adres zmiennej a STORE ; przypisanie Marcin Benke (MIM UW) Metody Realizacji Języków Programowania 6 grudnia 2010 31 / 1

Przykład 2 kod procedury r c.d. 0 ; miejsce na wynik FP LOAD ; SL dla s na stos s CALL ; skok ze śladem do s DROP ; usuwamy SL DROP ; usuwamy miejsce na wynik 0 ; miejsce na wynik FP LOAD 2 ADD LOAD ; adres ramki q 2 ADD LOAD ; SL dla wywołania q q CALL ; skok ze śladem do q DROP ; usuwamy SL DROP ; usuwamy miejsce na wynik DROP ; usuwamy zmienną c FP STORE ; wracamy do poprzedniej ramki GOTO ; i do miejsca wywołania Marcin Benke (MIM UW) Metody Realizacji Języków Programowania 6 grudnia 2010 32 / 1

Realizacja konstrukcji języków obiektowych W obiektowych językach programowania każdy obiekt posiada pewna wiedzę, przechowywana na zmiennych instancyjnych (zmiennych obiektowych), ma również określone umiejętności reprezentowane przez metody. To, jakie zmienne instancyjne i jakie metody posiada obiekt danej klasy, wynika z definicji tej klasy oraz z definicji klas, z których dziedziczy bezpośrednio lub pośrednio. W dalszej części wykładu omówimy realizację mechanizmów obiektowości dla języka programowania, w którym każda klasa może dziedziczyć z co najwyżej jednej klasy (języka z pojedyńczym dziedziczeniem). Marcin Benke (MIM UW) Metody Realizacji Języków Programowania 6 grudnia 2010 33 / 1

Zmienne instancyjne Każdy obiekt posiada zmienne zdefiniowane w jego klasie, a także zmienne odziedziczone z nadklas. Reprezentacja obiektów jest analogiczna do rekordów w obszarze pamięci zajętym przez obiekt znajduja się wartości jego zmiennych instancyjnych. Kolejność tych zmiennych ma być zgodna z hierarchia dziedziczenia zmienne zdefiniowane w klasie obiektu musza się znaleźć na końcu, przed nimi sa zmienne z klasy dziedziczonej itd. w górę hierarchii dziedziczenia. Marcin Benke (MIM UW) Metody Realizacji Języków Programowania 6 grudnia 2010 34 / 1

Np. w programie zawierajacym definicje klas: class A { var w:integer; procedure pisza { write(w)} } class B extends A { var x,y:integer; procedure piszb { write(w,x,y) } } class C extends B { var z:integer; procedure piszc { write(w,x,y,z) } } metody pisz... wypisuja wartości wszystkich zmiennych obiektu danej klasy. Marcin Benke (MIM UW) Metody Realizacji Języków Programowania 6 grudnia 2010 35 / 1

W programie tym, obiekty klasy A będa zawierały jedna zmienna: w obiekty klasy B trzy zmienne uporzadkowane w kolejności: w x y a obiekty klasy C cztery zmienne w kolejności: w x y z Przyjęcie takiej kolejności jest konieczne, by umożliwić metodom danej klasy prawidłowe działanie zarówno dla obiektów tej klasy, jak i jej podklas. Musimy zagwarantować, by w obiekcie dziedziczacym zmienna znajdowała się ona w tym samym miejscu, co w obiektach klasy dziedziczonej. W naszym przypadku, zarówno w obiektach klasy B jak i klasy C, zmienne x i y sa odpowiednio na 2 i 3 pozycji. Metoda piszb wie pod jakim przesunięciem te zmienne się znajduja niezależnie od tego, czy zostanie wywołana dla obiektu klasy B czy C. Marcin Benke (MIM UW) Metody Realizacji Języków Programowania 6 grudnia 2010 36 / 1

Metody wirtualne Wywołanie metody w językach obiektowych różni się od wywołania funkcji/procedury w językach proceduralnych dwoma elementami: metoda otrzymuje jako dodatkowy ukryty parametr obiekt, dla którego ma sie wykonać. W kodzie metody będziemy się odwoływali do tego parametru za pomoca słowa self. W językach obiektowych występuje mechanizm metod wirtualnych, co oznacza, że decyzja o wyborze metody jest podejmowana podczas wykonania programu, a nie podczas kompilacji. Gdy obiekt otrzyma komunikat, reaguje w sposób zależny od swojej klasy. Jeśli w tej klasie jest metoda o nazwie takiej, jak nazwa komunikatu, wywołujemy ja, jeśli nie, to szukamy w nadklasie itd. Marcin Benke (MIM UW) Metody Realizacji Języków Programowania 6 grudnia 2010 37 / 1

Metody wirtualne przykład Np. w programie zawierajacym deklaracje klas: class A { procedure nazwa { write( A ) } procedure pisz { write( To jest obiekt klasy ); self.nazwa } } class B extends A { procedure nazwa { write( B )} } var p:a; wykonanie instrukcji: p := new A; p.pisz wypisze "To jest obiekt klasy A", a wykonanie: p:= new B; p.pisz wypisze "To jest obiekt klasy B". Marcin Benke (MIM UW) Metody Realizacji Języków Programowania 6 grudnia 2010 38 / 1

Tablica metod wirtualnych Powszechnie stosowanym rozwiazaniem jest wyposażenie obiektu w tzw. tablicę metod wirtualnych, zawierajac a adresy kodu odpowiednich metod. W językach z typami statycznymi, dopuszczalne komunikaty sa znane podczas kompilacji. Można je ponumerować i reprezentować tablicę metod wirtualnych za pomoca zwykłej tablicy V, gdzie V [k] zawiera adres metody, która należy wykonać w odpowiedzi na komunikat numer k. wysłanie komunikatu k wymaga skoku ze śladem pod adres V [k]. Pozostałe elementy protokołu będa takie same, jak w przypadku zwykłych funkcji. Wybór metody zależy tylko od klasy obiektu; wszystkie obiekty danej klasy moga mieć wspólna tablicę metod wirtualnych. W samym obiekcie umieszczamy jedynie adres tej tablicy. Marcin Benke (MIM UW) Metody Realizacji Języków Programowania 6 grudnia 2010 39 / 1

Budowa tablic metod wirtualnych Budowa tablic metod wirtualnych oraz numerowanie komunikatów odbywa się podczas kompilacji, na etapie analizy kontekstowej. Tablice metod wirtualnych dla poszczególnych klas budujemy w kolejności przejścia drzewa dziedziczenia "z góry na dół". Tablica metod wirtualnych dla podklasy powstaje z tablicy dla nadklasy przez dodanie adresów metod zdefiniowanych w tej klasie. Jeśli metoda była już zdefiniowana "wyżej" w hierarchii, czyli jest redefiniowana, jej adres wpisujemy na pozycję metody redefiniowanej. Jeśli metoda pojawia się na ścieżce dziedziczenia pierwszy raz, jej adres wpisujemy na pierwsze wolne miejsce w tablicy metod wirtualnych. Marcin Benke (MIM UW) Metody Realizacji Języków Programowania 6 grudnia 2010 40 / 1