1 From: MX%"antek@mimuw.edu.pl" 1-MAR-1993 17:47:52.39
\r
6 Date: Mon, 1 Mar 93 14:59:27 GMT
\r
7 From: antek@mimuw.edu.pl
\r
8 To: salwicki@pauvx1.univ-pau.fr
\r
23 \^\ \ \ \ \ \ \ \ \ \ \ \"PRZENASZALNY RUNNING SYSTEM NOWEGO LOGLANU\ \ \ \ \ \ \ \ \ \ \^
\r
27 \^\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ NAPISANY W J\(E\"ZYKU C\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \^
\r
43 \^\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \1Antoni Kreczmar\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \^
\r
61 Poni\2x\1szy kr\2o\1tki opis Running Systemu dla \ nowego \ Loglanu \ opiera
\r
64 si\2e \ \1w \ du\2x\1ym \ stopniu \ na \ poprzednich \ dokumentacjach. \ \ Przede
\r
67 wszystkim na opisie Running \ Systemu \ Loglanu-82 \ oraz \ na \ dw\2o\1ch
\r
70 pracach opublikowanych, \ tj. \ G.Cioni, \ "Programmed \ deallocation
\r
73 without \ dangling \ reference" \ IPL \ 18(1984) \ pp.179-187, \ \ oraz
\r
76 M.Krause, \ A.Kreczmar, \ H.Langmaack, \ A.Salwicki, \ M.Warpechowski
\r
79 "Algebraic approach to ...." w Lecture Notes in Computer \ Science
\r
82 Springer 208, pp.134-156. W pierwszej z tych prac \ opisano \ system
\r
85 adresowania \ po\2s\1redniego \ dla \ Loglanu, \ \ a \ \ w \ \ drugiej \ \ dosy\2c
\r
88 \1skomplikowane \ algorytmy \ poprawiania \ \ tablicy \ \ Display \ \ oraz
\r
91 adresowania nielokalnego dla j\2e\1zyk\2o\1w z metodami dziedziczenia \ na
\r
94 r\2ox\1nych poziomach. Bez znajomo\2s\1ci \ tych \ dw\2o\1ch \ prac \ zrozumienie
\r
97 poni\2x\1szego kr\2o\1tkiego raportu jest niezwykle trudne. Radzimy \ wi\2e\1c
\r
100 przed przyst\2a\1pienie do czytania niniejszego tekstu zapozna\2c \ \1si\2e
\r
103 \1z tymi dwiema pracami, \ jak \ r\2o\1wnie\2x \ \1z \ dokumentacj\2a \ \1w \ dw\2o\1ch
\r
106 poprzednich jej postaciach (dla Loglanu-82 w \ pe\2l\1ni \ uruchominego
\r
109 i dla Loglanu-84 w pr\2o\1bnej wersji loglanowej). \,
\r
115 Nowy RS system dla nowego Loglanu \ zosta\2l \ \1napisany \ najpierw \ w
\r
118 Loglanie-82, \ a \ nast\2e\1pnie \ w \ j\2e\1zyku \ C. \ Wyb\2o\1r \ j\2e\1zyka \ C \ by\2l
\r
121 \1nieprzypadkowy. Ot\2ox \1w j\2e\1zyku tym mo\2x\1na wyrazi\2c \ \1wiele \ w\2l\1asno\2s\1ci
\r
124 niskopoziomowych, a posiada \ on \ tak\2x\1e \ wszystkie \ zalety \ j\2e\1zyka
\r
127 wysokopoziomowego. Przet\2l\1umaczenie wersji loglanowej na j\2e\1zyk C
\r
130 nie \ przedstawia\2l\1o \ wi\2e\1kszych \ trudno\2s\1ci, \ umo\2x\1liwi\2l\1o \ natomiast
\r
133 stworzenie bardzo efektywnego systemu \2l\1atwego do przenoszenia. \,
\r
136 RS system napisany \ w \ C \ daje \ mo\2x\1liwo\2sc \ \1wykonywania \ programu
\r
139 loglanowego przet\2l\1umaczonego na j\2e\1zyk C. Taki \ spos\2o\1b \ realizacji
\r
142 Loglanu \ wydaje \ mi \ si\2e \ \1najprostszy. \ Napisanie \ kompilatora \ z
\r
145 Loglanu na C jest \ znacznie \ \2l\1atwiejsze \ ni\2x \ \1napisanie \ pe\2l\1nego
\r
148 kompilatora \ na \ docelow\2a \ \1maszyn\2e\1. \ Problem \ przenoszenia \ jest
\r
151 rozwi\2a\1zany w spos\2o\1b natychmiastowy. Ponadto kompilator taki mo\2x\1e
\r
154 korzysta\2c \1z bogactwa konstrukcji j\2e\1zyka C. Nie b\2e\1dzie problemu ze
\r
157 sta\2l\1ymi, \ \ instrukcjami \ \ \ steruj\2a\1cymi \ \ \ w \ \ \ obr\2e\1bie \ \ \ modu\2l\1u,
\r
160 wej\2s\1ciem-wyj\2s\1ciem, \2l\1a\2n\1cuchami itp. \ Niezwykle \ upro\2s\1ci \ si\2e \ \1sam
\r
163 proces translacji. Wyra\2x\1enia mog\2a \1pozosta\2c \1w prawie niezmienionej
\r
166 postaci - jedynie dost\2e\1p do zmiennych loglanowych b\2e\1dzie wymaga\2l
\r
169 \1wywo\2l\1ywania specjalnych makro - ale proces \2l\1adowania \ rejestr\2o\1w,
\r
172 optymalizacji lokalnej itd. przerzucony zostanie na system \ C.
\r
175 A \ przecie\2x \ \1jest \ to \ system \ niezwykle \ \ efektywny. \ \ Wi\2e\1kszo\2sc
\r
178 \1kompilator\2o\1w C daje kod \ dobrze \ zoptymalizowany. \ W \ ten \ prosty
\r
181 spos\2o\1b mo\2x\1emy wykorzysta\2c \1si\2le \1tego j\2e\1zyka \ zostawiaj\2a\1c \ troski
\r
184 techniczne \ \ \ (rejestry, \ \ \ arytmetyka \ \ \ maszyny, \ \ \ \ etykiety,
\r
187 optymalizacja) systemowi C. \,
\r
193 Opisany poni\2x\1ej system sk\2l\1ada si\2e \1z dwu \ plik\2o\1w \ : \ Rs.c \ oraz
\r
196 Rsdata.h. Plik Rsdata.h jest \ tzw. \ plikiem \ nag\2lo\1wkowym \ (header
\r
199 file). W nim wyra\2x\1ono wszystkie wsp\2o\1lne struktury \ danych \ oraz
\r
202 podstawowe zmienne. Na pliku Rs.c znajduje \ si\2e \ \1natomiast \ pe\2l\1na
\r
205 biblioteka \ \ Running \ \ Systemu. \ \ Tekst \ \ programu \ \ \ loglanowego
\r
208 przet\2l\1umaczony na C musi w\2la\1cza\2c \1za pomoc\2a \1instrukcji \ include
\r
211 plik Rsdata.h. W taki sam spos\2o\1b w\2la\1czany \ jest \ ten \ plik \ przez
\r
225 Warszawa, Sierpie\2n \11988\,
\r
237 2. Opis struktur danych na pliku Rsdata.h
\r
243 Na pliku \ tym \ znajduj\2a \ \1si\2e \ \1deklaracje \ struktury \ prototyp\2o\1w \ i
\r
246 offset\2o\1w. Zajmiemy \ si\2e \ \1najpierw \ struktur\2a \ \ \1prototypu. \ \ Ma \ \ on
\r
249 nast\2e\1puj\2a\1c\2a \1posta\2c\1: \,
\r
255 \4struct \3Prototype
\r
267 \ \4int \3lspan\1, \3rspan\1;
\r
270 \ \4int \3references\1;
\r
273 \ \4int \3decl\1, \3level\1;
\r
276 \ \4int \3lastwill\1;
\r
279 \ \4int \3permadd\1;
\r
282 \ \4int \3Sloffset\1, \3Dloffset\1;
\r
285 \ \4int \3Statoffset\1, \3Lscoffset\1;
\r
288 \ \4int \3handlist\1;
\r
291 \ \4int \3pref\1, \3pslength\1;
\r
300 Atrybut \3kind \1definiuje rodzaj \ prototypu. \ Mamy \ nast\2e\1puj\2a\1ce \ ich
\r
303 rodzaje: CLASS, SUBROUTINE, PROCESS, COROUTINE, HANDLER, \ RECORD,
\r
306 PRIMITARRAY, REFARRAY, SUBARRAY, STRUCTARRAY, POINTARRAY. \ Pi\2ec
\r
309 \1pierwszych nie wymaga wyja\2s\1nie\2n\1. RECORD jest klas\2a \1bez kodu i bez
\r
312 innych modu\2lo\1w zadeklarowanych \ wewn\2a\1trz. \ Ten \ rodzaj \ prototypu
\r
315 istnia\2l \1ju\2x \1w poprzedniej wersji Running Systemu. Ostanich pi\2ec
\r
318 \1rodzaj\2o\1w dotyczy tablic. PRIMITARRAY jest tablic\2a \ \1o \ elementach
\r
321 typu pierwotnego, \ REFARRAY \ jest \ tablic\2a \ \1typu \ referencyjnego,
\r
324 SUBARRAY jest tablic\2a\1, kt\2o\1rej elementami s\2a \1domkni\2e\1cia \ procedur,
\r
327 STRUCTARRAY jest tablic\2a \1o elementach typu z\2l\1o\2x\1onego \ i \ wreszcie
\r
330 POINTARRAY \ jest \ tablic\2a \ \1typu \ \ referencyjnego, \ \ jednak\2x\1e \ \ o
\r
333 elementach daj\2a\1cych adresy po\2s\1rednie bez licznik\2o\1w. \ Taki \ typ
\r
336 dodatkowy wprowadzili\2s\1my w nowej wersji \ RS \ w \ celu \ osi\2a\1gni\2e\1cia
\r
339 wi\2e\1kszej efektywno\2s\1ci kodu. Zamiast \ pe\2l\1nego \ adresu \ wirtualnego
\r
342 [adres po\2s\1redni, licznik] niekt\2o\1re referencje s\2a \ \1postaci \ [adres
\r
345 po\2s\1redni]. \ Nie \ daj\2a \ \1one \ oczywi\2s\1cie \ gwarancji \ \ poprawno\2s\1ci
\r
348 adresowania \ (mo\2x\1e \ wyst\2a\1pi\2c \ \1tzw. \ nieokre\2s\1lona \ \ referencja),
\r
351 nimniej, \ je\2s\1li \ u\2x\1ytkownik \ jest \ pewny \ \ poprawno\2s\1ci \ \ swoich
\r
354 adresowa\2n\1, mo\2x\1e cz\2esc \1lub \ wszystkie \ referencje \ zaznaczy\2c \ \1jako
\r
357 proste. Poniewa\2x \1typy \ tablicowe \ s\2a \ \1rozr\2ox\1niane \ przez \ atrybut
\r
360 \3kind, \1w\2s\1r\2o\1d rodzaj\2o\1w typ\2o\1w pojawi\2l \1si\2e \1tak\2x\1e typ POINTERARRAY. \,
\r
366 Drugim atrybutem prototypu jest \3num\1. Wskazuje on \ pozycj\2e \ \1danego
\r
369 prototypu w tablicy PROT [] definiuj\2a\1cej wszystkie prototypy. \,
\r
375 Atrybuty \3lspan \1i \3rspan \1definiuj\2a \ \1rozmiar \ obiektu \ danego \ typu.
\r
378 Wszystkie obiekty alokowane \ s\2a \ \1w \ tablicy \ M[ \ ]. \ Maj\2a\1c \ adres
\r
381 obiektu \3am \1na lewo mamy rozmiar \ \3lspan\1, \ na \ prawo \ \3rspan\1, \ czyli
\r
384 obiekt \ zajmuje \ elementy \ tablicy \ M[\3am-lspan\1..\3am\1+\3rspan\1]. \ Adres
\r
387 prototypu usytuowany jest zawsze w s\2l\1owie M[\3am\1], tzn. maj\2a\1c adres
\r
390 obiektu na zmiennej \3am\1, w\2l\1a\2s\1nie M[\3am\1] = \ \3num \ \1, \ gdzie \ \3num \ \1jest
\r
393 adresem prototypu tego \ obiektu \ w \ tablicy \ PROT. \ Tablice \ maj\2a
\r
396 \1rozmiar definiowany dynamicznie. W s\2l\1owie \ M[\3am\1] \ jest \ zapisany
\r
399 stosowny \ numer \ prototypu, \ natomiast \ \ dwa \ \ kolejne \ \ s\2l\1owa
\r
402 definiuj\2a \1doln\2a \ \1i \ g\2o\1rn\2a \ \1granice \ wska\2z\1nika. \ Rozmiar \ elementu
\r
405 tablicy w przypadku PRIMITARRAY podawany jest za pomoc\2a \ \1atrybutu
\r
414 Pozosta\2l\1e atrybuty nie s\2a \1konieczne w przypadku tablic.
\r
420 Atrubut \3references \1definiuje struktur\2e \1referencji prototypu. \ Jest
\r
423 to po prostu indeks w tablicy OFF[], kt\2o\1ra \ definiuje \ wszystkie
\r
426 rodzaje struktur referencji (patrz definicja OFF poni\2x\1ej). \,
\r
432 Atrybuty \3decl \1i \ \3level \ \1odnosz\2a \ \1si\2e \ \1do \ struktury \ zagnie\2x\1d\2x\1e\2n
\r
435 \1programu. Mianowicie \3decl \1jest indeksem w PROT \ ojca \ statycznego
\r
438 danego modu\2l\1u, natomiast \3level \1jest g\2le\1boko\2s\1ci\2a \1zagnie\2x\1d\2x\1enia. \,
\r
444 Atrybut \3lastwill \1okre\2s\1la miejsce w module, od kt\2o\1rego rozpoczynaj\2a
\r
447 \1si\2e \1instrukcje lastwill. \ W \ jaki \ spos\2o\1b \ modeluje \ si\2e \ \1kontrol\2e
\r
450 \1sterowania podamy w punktach 4 i 10. \,
\r
456 Nast\2e\1pny atrybut \3permadd \1jest wsp\2o\1lnym adresem dla \ permutacji \ i
\r
459 inwersji permutacji numer\2o\1w displaya. Mianowicie plik \ loglanowy
\r
462 definiuje dwie tablice \3perm\1[] i \3perminv\1[], kt\2o\1re \ musz\2a \ \1zawiera\2c
\r
465 \1te permutacji. \ Przyk\2l\1adowo, \ dla \ \3perm\1[] \ = \ {0,1,2,0,2,1} \ oraz
\r
468 \3perminv\1[] = {0,1,2,0,2,1}, indeks \3permadd\1=0 dla warto\2s\1ci \ \3level\1=2
\r
471 okre\2s\1la permutacj\2e \1{0,1,2} \ (i \ te \ sam\2a \ \1odwrotn\2a\1), \ natomiast
\r
474 \3permadd\1=2 dla \3level \1te\2x \1r\2o\1wnym 2 daje perm={0,2,1} \ (i \ podobnie
\r
477 te sam\2a \1odwrotn\2a\1}. \,
\r
483 Cztery \ kolejne \ atrybuty \ \ (\3Sloffset\1, \ \ \3Dloffset\1, \ \ \3Statoffset\1,
\r
486 \3Lscoffset\1) definiuj\2a \1adresy wzgl\2e\1dne (offsety) czterech zmiennych
\r
489 systemowych Sl, Dl, Statsl i Lsc. Ka\2x\1dy \ modu\2l \ \1posiadaj\2a\1cy \ kod
\r
492 musi \ mie\2c \ \1okre\2s\1lon\2a \ \1pozycj\2e \ \1Sl \ ojca, \ Dl \ \ ojca, \ \ lokalnego
\r
495 sterowania Lsc i licznika Sl syn\2o\1w (Statsl). \ O \ tych \ zmiennych
\r
498 systemowych b\2e\1dziemy m\2o\1wi\2c \1za chwil\2e\1. Tutaj natomiast \ chcieli\2s\1my
\r
501 zwr\2o\1ci\2c \1uwag\2e \1na to, \2x\1e w poprzedniej \ wersji \ RS \ offsety \ tych
\r
504 zmiennych by\2l\1y podawane w prototypie (ich pozycja \ by\2l\1a \ ustalona
\r
507 na ko\2n\1cu obiektu). Wprowadzenie offset\2o\1w zmiennych systemowych do
\r
510 prototyp\2o\1w skomplikuje kompilacj\2e\1, ale przyspieszy i ujednorodni
\r
513 RS. Dost\2e\1p do tych zmiennych \ b\2e\1dzie \ bowiem \ taki \ sam \ jak \ do
\r
516 innych \ zmiennych \ wprowadzonych \ przez \ \ u\2x\1ytkownika \ \ czy \ \ te\2x
\r
525 Atrybut \3handlist \1definiuje list\2e \1handler\2o\1w zadeklarowanych w danym
\r
528 module. Jest to indeks w \ tablicy \ HL[], \ gdzie \ zdefiniowane \ s\2a
\r
531 \1wszystkie takie listy. \ Tablica \ HL \ jest \ typu \ Hlstelem \ postaci
\r
534 nast\2e\1puj\2a\1cej: \,
\r
540 \4struct \3Hlstelem
\r
549 \ \4int \3signlist\1;
\r
564 Atrybut \3hand \1jest indeksem w tablicy \ PROT \ w\2l\1a\2s\1ciwego \ handlera.
\r
567 Natomiast atrybut \3signlist \ \1jest \ indeksem \ w \ tablicy \ SL[] \ typu
\r
570 \3Sgelem\1, \ gdzie \ okre\2s\1lone \ s\2a \ \1numery \ sygna\2lo\1w \ zwi\2a\1zane \ z \ \ tym
\r
573 handlerem. Typ \3Sgelem \1ma posta\2c \1nast\2e\1puj\2a\1c\2a\1: \,
\r
585 \ \4int \3signalnum\1;
\r
600 W ka\2x\1dym elemencie tablicy \ SL[] \ mamy \ numer \ sygna\2l\1u \ \3signalnum\1,
\r
603 kt\2o\1ry jest warto\2s\1ci\2a \1absolutn\2a \1budowan\2a \1przez kompilator. \ Atrybut
\r
606 \3next \1pokazuje na kolejny element takiej \ listy \ w \ SL[]. \ Podobnie
\r
609 zreszt\2a \1atrybut \3next \1w HL[] wskazuje na nast\2e\1pny handler \ zwi\2a\1zany
\r
612 z danym modu\2l\1em. Koniec ka\2x\1dej takiej listy \ (w \ obu \ przypadkach)
\r
615 okre\2s\1la warto\2sc \3next\1=-1 (tak wybrano z uwagi na \ adresowanie \ w \ C
\r
624 Atrybut \3handlist \1wyst\2e\1puje tak\2x\1e w prototypie handlera. \ Okre\2s\1la
\r
627 on jedynie, \ czy \ handler \ ten \ odpowiada \ na \ wszystkie \ sygna\2l\1y
\r
630 (others), \ czy \ \ te\2x \ \ \1jest \ \ deklarowany \ \ jako \ \ handler \ \ dla
\r
633 wyspecyfikowanych \ numer\2o\1w \ sygna\2lo\1w. \ W \ \ pierwszym \ \ przypadku
\r
636 warto\2sc \ \1tego \ atrybutu \ jest \ 1 \ (hanlder \ dla \ \ others), \ \ w
\r
639 pozosta\2l\1ych przypadkach warto\2sc \1tego atrybutu jest 0. \,
\r
648 Dwa ostatnie atrybuty w prototypie ( \ \3pref\1, \ \3pslength\1) \ okre\2s\1laj\2a
\r
651 \1struktur\2e \1prefiksowania. Nie musz\2a \1one \ wyst\2e\1powa\2c \ \1w \ przypadku
\r
654 prototyp\2o\1w dla handler\2o\1w, gdy\2x \1handler nie mo\2x\1e by\2c \1prefiksowany.
\r
657 Atrybut \3pref \1jest indeksem w tablicy PROT modu\2l\1u \ prefiksuj\2a\1cego
\r
660 (-1 gdy nie istnieje), \ atrybut \ \3pslength \ \1jest \ d\2l\1ugo\2s\1ci\2a \ \1ci\2a\1gu
\r
663 prefiksuj\2a\1cego. \,
\r
669 Pozosta\2l\1a do \ om\2o\1wienia \ struktura \ referencji. \ Ot\2ox \ \1z \ powodu
\r
672 wprowadzenia bogactwa typ\2o\1w z\2l\1o\2x\1onych w nowym Loglanie, struktura
\r
675 referencji \ w \ obiektach \ jest \ stosunkowo \ skomplikowana. \ Takie
\r
678 struktury opisuje tablica OFF[] typu \3Offsets\1. \,
\r
693 \ \4int \3size\1, \3num\1;
\r
696 \ \4int \3length\1, \3finish\1;
\r
702 \ \4int \3references\1;
\r
714 Atrybut \3kind \1jest nast\2e\1puj\2a\1cych \ rodzaj\2o\1w: \ SIMPLELIST, \ SEGMENT,
\r
717 REPEATED \ oraz \ COMBINEDLIST. \ SIMPLELIST \ jest \ list\2a \ \ \1zwyk\2l\1ych
\r
720 offset\2o\1w \ zmiennych \ referencyjnych \ w \ obiekcie. \ SEGMENT \ jest
\r
723 szczeg\2o\1ln\2a \1postaci\2a \ \1takiej \ listy, \ gdy \ te \ offsety \ zajmuj\2a
\r
726 \1kolejne miejsca w pami\2e\1ci (ten typ wprowadzili\2s\1my \ ze \ wzgl\2e\1du
\r
729 na tablice referencyjne, jakkolwiek jest \ on \ sprowadzalny \ do
\r
732 przypadku poprzedniego). REPEATED jest \ n-krotn\2a \ \1iteracj\2a \ \1danej
\r
735 struktury referencyjnej. COMBINEDLIST jest list\2a \1by\2c \1mo\2x\1e r\2ox\1nych
\r
738 struktur referencji. \,
\r
744 Atrybut \3size \1okre\2s\1la ca\2l\1kowit\2a \1d\2l\1ugo\2sc \1opisywanej \ struktury \ Dla
\r
747 SIMPLELIST musi to \ by\2c \ \1d\2l\1ugo\2sc \ \1ca\2l\1ego \ obiektu, \ dla \ SEGMENT
\r
750 r\2o\1wnie\2x \1d\2l\1ugo\2sc \1ca\2l\1ego obiektu, dla REPEATED musi to by\2c \ \1d\2l\1ugo\2sc
\r
753 \1powtarzanej struktury, i ostatecznie dla COMBINEDLIST ma to \ by\2c
\r
756 \1d\2l\1ugo\2sc \ \1struktury \ wewn\2a\1trz \ kt\2o\1rej \ podawane \ s\2a \ \1wska\2z\1niki \ \ do
\r
765 Kolejny \ atrybut \ \3num \ \1definiuje \ indeks \ w \ tablicy \ \ OFF \ \ danej
\r
774 Znaczenie atrybutu \3length \1jest \ wieloznaczne. \ Dla \ SIMPLELIST
\r
777 \3length \1jest d\2l\1ugo\2s\1ci\2a \1listy offset\2o\1w. Dla SEGMENT \ \3length \ \1jest
\r
780 pozycj\2a \1pierwszego,a \3finish \1ostatniego elementu \ segmentu. \ Dla
\r
783 REPEATED \3length \1jest \ krotno\2s\1ci\2a \ \1powt\2o\1rzenia \ podstruktury. \ Dla
\r
786 COMBINEDLIST \3length \1jest d\2l\1ugo\2s\1ci\2a \1listy. \,
\r
792 Atrybut \3head \1jest indeksem w tablicy EL[], gdzie \ zakodowane \ s\2a
\r
795 \1listy struktur referencji. Typem tej tablicy jest \3Elem\1: \,
\r
807 \ \4int \3offset\1;
\r
813 \ \4int \3references\1;
\r
822 W tablicy tej atrybut \3offset \1definiuje odpowiedni offset a \ \3next
\r
825 \1jest jak zwykle wska\2z\1nikiem do \ nast\2e\1pnego \ elementu \ listy. \ Dla
\r
828 typu SIMPLELIST ka\2x\1dy taki \ offset \ mo\2x\1e \ by\2c \ \1offsetem \ zmiennej
\r
831 referencyjnej pe\2l\1nej lub tylko adresem po\2s\1rednim, ale tak\2x\1e \ mo\2x\1e
\r
834 by\2c \1offsetem domkni\2e\1cia procedury (czyli pary <SL, adres kodu> ).
\r
837 Gdy atrybut \3references \1jest 0, mamy referencje pe\2l\1n\2a\1, gdy jest \ 1
\r
840 jest to adres po\2s\1redni, wreszcie gdy jest 2 \ jest \ to \ domkni\2e\1cie
\r
849 Dla typu COMBINEDLIST atrybut \3references \1okre\2s\1la indeks w tablicy
\r
852 OFF wskazywanej podstruktury referencji. \,
\r
861 W przypadku typu SEGMENT atrybut \ \3head \ \1mo\2x\1e \ jeszcze \ okre\2s\1la\2c
\r
864 \1rodzaj referencji. Gdy \3head \1= 0, mamy segment pe\2l\1nych referencji,
\r
867 gdy jest 1 jest to segment adres\2o\1w po\2s\1rednich, gdy jest 2 jest to
\r
870 segment domkni\2ec \1procedur.\,
\r
879 Dla ostatniego atrybutu \3references \1w \ typie \ \3Offsets \ \1mamy \ jedno
\r
882 zadanie. Powinien on okre\2s\1la\2c \1dla typu REPEATED indeks w \ tablicy
\r
885 OFF powtarzanej struktury. \,
\r
891 Powy\2x\1szy system wprowadzania \ struktury \ prototyp\2o\1w \ jest \ dosy\2c
\r
894 \1niezr\2e\1czny, je\2s\1li musi by\2c \1wykonany r\2e\1cznie. Troch\2e \1w \ tym \ wina
\r
897 j\2e\1zyka C. Mo\2x\1na by\2l\1o \ wprowadzi\2c \ \1typ \ union, \ kt\2o\1ry \ przypomina
\r
900 rekordy z \ wariantami, \ ale \ w\2o\1wczas \ nie \ mo\2x\1naby \ podawa\2c \ \1tych
\r
903 struktur przez definicje w deklaracji (odp. DATA \ w \ Fortranie).
\r
906 Zatem przyj\2al\1em \ takie \ rozwi\2a\1zanie \ przez \ zwyk\2la \ \1struktur\2e\1. \ Z
\r
909 drugiej strony translator z Loglanu na C mo\2x\1e bez k\2l\1opotu budowa\2c
\r
912 \1tak\2a \1struktur\2e\1. \,
\r
921 3. Struktury Dl i Sl
\r
927 Struktura Dl zachowana jest taka \ jak \ w \ Simuli \ i \ Loglanie-82.
\r
930 Aktywny wsp\2ol\1program jest \2l\1a\2n\1cuchem Dl, zawieszony jest \ cyklem
\r
933 Dl. \ Nowy \ Loglan \ usun\2al \ \ \1Detach, \ \ gdy\2x \ \ \1wprowadzi\2l \ \ \1zmienn\2a
\r
936 \1LAST_ATTACH - \ wskazuj\2a\1c\2a \ \1na \ ostatni \ wsp\2ol\1program \ wykonuj\2a\1cy
\r
939 Attach(X). Zako\2n\1czenie wsp\2ol\1programu \ jest \ sygnalizowane \ b\2le\1dem
\r
942 (propozycja \ \ \ \ Marka \ \ \ \ Warpechowskiego). \ \ \ \ Wykonuje \ \ \ \ \ si\2e
\r
945 \1Attach(LAST_ATTACH) with Cor_Term (coroutine terminated), \ o \ ile
\r
948 LAST_ATTACH \ =/= \ \4none\1, \ w \ \ przeciwnym \ \ razie \ \ wykonuje \ \ si\2e
\r
951 \1Attach(My_Process) \ \ with \ \ Cor_Term. \ \ To \ \ \ rozwi\2a\1zanie \ \ \ jest
\r
954 metodologicznie uzasadnione i najprostsze. \,
\r
960 Dla \ wsp\2ol\1programu \ aktywnego \ warto\2sc \ \1Dl \ jest \ \ \4none\1. \ \ Pr\2o\1ba
\r
963 reaktywacji wsp\2ol\1programu aktywnego \ powoduje \ wys\2l\1anie \ sygna\2l\1u
\r
966 alarmowego. \ Wsp\2ol\1program \ \ zako\2n\1czony \ \ ma \ \ ustawion\2a \ \ \1warto\2sc
\r
969 \1lokalnego sterowania Lsc na 0. \ Pr\2o\1ba \ reaktywacji \ zako\2n\1czonego
\r
972 wsp\2ol\1programu powoduje wys\2l\1anie sygna\2l\1u. Zauwa\2x\1my na \ zako\2n\1czenie
\r
975 omawiania struktury Dl, \ \2x\1e \ Dl-link \ mo\2x\1e \ by\2c \ \1w \ tym \ systemie
\r
978 referencj\2a \1niepe\2l\1n\2a \1(tzn. tylko adresem po\2s\1rednim). \ Zyskujemy
\r
981 w ten spos\2o\1b na pami\2e\1ci i na czasie wykonania programu. \,
\r
987 Struktura Sl link\2o\1w \ tworzy \ drzewo. Problemem s\2a \ \1tylko \ usuwane
\r
990 obiekty procedur, \ funkcji \ i \ blok\2o\1w, \ po \ ich \ terminacji. \ W
\r
993 poprzedniej \ wersji \ przyj\2e\1li\2s\1my \ \ strategi\2e \ \ \1usuwania \ \ takich
\r
996 obiekt\2o\1w bez wzgl\2e\1du na konsekwencje. Mog\2l\1o si\2e \ \1zdarzy\2c\1, \ \2x\1e \ po
\r
999 pewnym \ czasie \ wznawiany \ dobrze \ \ okre\2s\1lony \ \ obiekt \ \ nie \ \ ma
\r
1002 okre\2s\1lonego otoczenia statycznego (Sl link przeci\2e\1ty). \ Umieli\2s\1my
\r
1005 wykry\2c \1takie przypadki, ale nie by\2l\1o to \ rozwi\2a\1zanie \ eleganckie.
\r
1008 Marek Lao \ zauwa\2x\1y\2l\1, \ \2x\1e \ lepiej \ by\2l\1oby \ u\2x\1y\2c \ \1zwyk\2l\1ej \ techniki
\r
1011 licznik\2o\1w referencji tylko \ dla \ tego \ przypadku. \ Mamy \ przecie\2x
\r
1014 \1licznik Statsl (poprzednio inaczej okre\2s\1lony), nale\2x\1y zastosowa\2c
\r
1017 \1go w spos\2o\1b nast\2e\1puj\2a\1cy. \,
\r
1023 Ka\2x\1de otwarcie nowego obiektu zwi\2e\1ksza o 1 \ licznik \ Statsl \ jego
\r
1026 statycznego ojca. Ka\2x\1de zako\2n\1czenie obiektu \ procedury \ (funkcji,
\r
1029 bloku) sprawdza, czy jego Statsl jest 0. Je\2s\1li tak, obiekt \ mo\2x\1na
\r
1032 usun\2ac\1, zmniejszy\2c \1Statsl o \ 1 \ dla \ jego \ ojca \ i \ powt\2o\1rzy\2c \ \1te
\r
1035 operacje dla takiego \ ojca \ (o \ ile \ jest \ to \ obiekt \ procedury,
\r
1038 funkcji lub bloku). Dla usuwanego za pomoc\2a \1kill \ obiektu \ klasy,
\r
1041 sprawdzamy \ najpierw \ jego \ Statsl, \ \ i \ \ post\2e\1pujemy \ \ podobnie.
\r
1044 Pozostaje rozwi\2a\1za\2c \1poprawnie problem usuwania wsp\2ol\1program\2o\1w. \,
\r
1050 Zabicie zawieszonego wsp\2ol\1programu polega na \ zabiciu \ stosownego
\r
1053 cyklu Dl. Najpierw przegl\2a\1damy taki cykl i sprawdzamy, \ czy \ jego
\r
1056 wszystkie obiekty maj\2a \1Statsl \ r\2o\1wny \ 0. \ Je\2s\1li \ nie, \ wywo\2l\1ujemy
\r
1059 sygna\2l \1alarmowy. Je\2s\1li natomiast wszystkie \ s\2a \ \1usuwalne, \ mo\2x\1emy
\r
1062 przyst\2a\1pi\2c \1do kolejnego ich usuwania. Aby \ to \ zrobi\2c \ \1poprawnie,
\r
1065 nale\2x\1a\2l\1oby stosowa\2c \1operacj\2e \1przej\2s\1cia po Sl-\2l\1a\2n\1cuchu dla ka\2x\1dego
\r
1068 obiektu usuni\2e\1tego (tak jak \ dla \ obiektu \ klasy). \ Ale \ przecie\2x
\r
1071 \1mogliby\2s\1my usun\2ac \1jaki\2s \1obiekt jeszcze \ nieusuni\2e\1ty \ z \ usuwanego
\r
1074 w\2l\1a\2s\1nie cyklu wsp\2ol\1programu. Aby unikn\2ac \1tej sytuacji, \ odwracamy
\r
1077 najpierw \ cykl \ wsp\2ol\1programu. \ Zabijaj\2a\1c \ obiekty \ w \ kolejno\2s\1ci
\r
1080 odwrotnej (od g\2l\1owy wsp\2ol\1programu, nast\2e\1pnie syn dynamiczny itd),
\r
1083 mamy pewno\2sc\1, \ \2x\1e \ nie \ usuniemy \ przy \ czyszczeniu \ kolejnych
\r
1086 \2l\1a\2n\1cuch\2o\1w Sl \2x\1adnego pozosta\2l\1ego elementu \ cyklu. \ Wynika \ to \ z
\r
1089 w\2l\1asno\2s\1ci Sl \ i \ Dl \ \2l\1a\2n\1cuch\2o\1w \ - \ nie \ mog\2a \ \1i\2sc \ \1w \ przeciwnych
\r
1092 kierunkach, tzn. je\2s\1li jest Dl droga od A do B to nie ma Sl drogi
\r
1095 od B do A. \ W \ drugiej \ fazie \ usuwania \ wsp\2ol\1programu \ zmieniamy
\r
1098 orientacj\2e \1cyklu. W trzeciej, ju\2x \1bezpiecznie mo\2x\1emy usun\2ac \ \1ca\2l\1y
\r
1101 cykl \ czyszcz\2a\1c \ po \ \ drodze \ \ \2l\1a\2n\1cuchy \ \ Sl. \ \ W \ \ ten \ \ spos\2o\1b
\r
1104 rozwi\2a\1zali\2s\1my, \ chyba \ dostatecznie \ \ poprawnie \ \ i \ \ elegancko,
\r
1107 problemy czyszczenia pami\2e\1ci w Loglanie. Ponadto taka \ struktura
\r
1110 Sl pozwala \ na \ zast\2a\1pi\2e\1nie \ pe\2l\1nych \ referencji \ dla \ Sl \ link\2o\1w
\r
1113 adresami po\2s\1rednimi (tak jak to \ mia\2l\1o \ miejsce \ w \ przypadku \ Dl
\r
1116 link\2o\1w). Zawsze bowiem warto\2sc \1Sl jest \ dobrze \ okre\2s\1lona \ i \ nie
\r
1119 wymaga sprawdzenia, tak jak to mia\2l\1o miejsce w \ starym \ Loglanie,
\r
1122 tzn. czy okre\2s\1la jeszcze istniej\2a\1cy obiekt. \,
\r
1128 Zmiana warto\2s\1ci atrybutu Statsl dotyczy \ tak\2x\1e \ u\2x\1ycia \ zmiennych
\r
1131 podprogramowych. Warto\2s\1ci\2a \1takiej \ zmiennej \ podprogramowej \ jest
\r
1134 domkni\2e\1cie procedury (<SL,adres kodu>). Poniewa\2x \1j\2e\1zyk w \ obecnej
\r
1137 postaci dopuszcza operowanie na zmiennych podprogramowych, system
\r
1140 musi dba\2c \1o to, by nieopatrznie nie usuwa\2c \1otoczenia \ statycznego
\r
1143 dla dost\2e\1pnego domkni\2e\1cia procedury, \ albowiem \ takie \ domkni\2e\1cie
\r
1146 mo\2x\1e by\2c \1w ka\2x\1dej chwili u\2x\1yte. Jak wi\2e\1c post\2e\1pujemy. Traktujemy
\r
1149 domkni\2e\1cia \ \ procedur \ \ jako \ \ specjalne \ \ zmienne \ \ referencyjne
\r
1152 (przypominam, \ \2x\1e \ odpowiednie \ SL \ linki \ \ mog\2a \ \ \1by\2c \ \ \1adresami
\r
1155 kr\2o\1tkimi). Dla tych specjalnych \ referencji \ stosujemy \ strategi\2e
\r
1158 \1reference counter, czyli ka\2x\1de \ podstawienie \ wymaga \ poprawienia
\r
1161 odpowiednich \ Statsl. \ Przy \ usuwaniu \ \ obiektu \ \ nale\2x\1y \ \ jednak
\r
1164 wszystkie takie zmienne przejrze\2c \1i \ tak\2x\1e \ poprawi\2c \ \1odpowiednie
\r
1167 Statsl. Ca\2l\1o\2sc \1jest bardzo prosta, wymaga jednak wyr\2ox\1nienia tych
\r
1170 referencji, co zosta\2l\1o zrobione w\2l\1a\2s\1nie w strukturze OFF.\,
\r
1176 4. Struktura sterowania lokalnego
\r
1182 Sterowanie lokalne w j\2e\1zyku C jest bardzo podobne \ do \ sterowania
\r
1185 lokalnego w Loglanie. Wszystkie p\2e\1tle \ loglanowe \ mo\2x\1na \ zast\2a\1pi\2c
\r
1188 \1przez ich \ odpowiedniki \ w \ j\2e\1zyku \ C. \ Podobnie \ z \ instrukcjami
\r
1191 warunkowymi i instrukcjami wyboru. Problem techniczny powstaje w
\r
1194 momencie przekazywanie sterowania pomi\2e\1dzy modu\2l\1ami \ Loglanowymi,
\r
1197 poniewa\2x \1ka\2x\1de takie przekazanie sterowania zawiesza \ wykonywanie
\r
1200 instrukcji modu\2l\1u aktywnego. Jak z tym \ problemem \ upora\2c \ \1si\2e \ \1w
\r
1203 j\2e\1zyku C. Modu\2l \1loglanowy przet\2l\1umaczony na odpowiedni modu\2l \1C ma
\r
1206 jako pierwsz\2a \1instrukcj\2e \1wygenerowan\2a \1przez kompilator instrukcj\2e
\r
1221 \4case \11: \4goto \1L1; \4break\1;
\r
1233 \4case \1n: \4goto \1Ln; \4break\1;
\r
1242 gdzie IC jest wsp\2o\1ln\2a \ \1zmienn\2a \ \1globaln\2a \ \1zadeklarowan\2a \ \1w \ pliku
\r
1245 Rsdata.h oraz etykiety L1,...,Ln definiuj\2a \1r\2ox\1ne \ punkty \ wej\2s\1cia
\r
1248 do modu\2l\1u. Ka\2x\1de \ przekazanie \ sterowania \ do \ innego \ modu\2l\1u \ za
\r
1251 pomoc\2a \1procedur systemowych RS \ (np. \ Go, \ Attach, \ itp.) \ wymaga
\r
1254 prawid\2l\1owego okre\2s\1lenia warto\2s\1ci \ IC, \ kt\2o\1ra \ jest \ zapami\2e\1tywana
\r
1257 przez RS w \ odpowiedniej \ lokacji \ obiektu \ (Lsc). \ Na \ przyk\2l\1ad,
\r
1260 wywo\2l\1anie procedury loglanowej ma posta\2c\1: \,
\r
1275 Przy ponownym wywo\2l\1aniu tego modu\2l\1u, na \ przyk\2l\1ad \ po \ powrocie \ z
\r
1278 wywo\2l\1anej \ procedury, \ odtworzona \ warto\2sc \ \1IC \ \ pozwala \ \ Running
\r
1281 Systemowi trafi\2c \1w poprawne miejsce modu\2l\1u, a wi\2e\1c w instrukcje po
\r
1284 wywo\2l\1aniu Go(...). \,
\r
1293 Pierwsze wej\2s\1cie do modu\2l\1u okre\2s\1la warto\2sc \1IC=1, zatem etykieta L1
\r
1296 musi \ wyst\2a\1pi\2c \ \1przed \ pierwsz\2a \ \1przet\2l\1umaczon\2a \ \1na \ C \ instrukcj\2a
\r
1299 \1loglanow\2a\1. \,
\r
1305 Jak ju\2x \1powiedzieli\2s\1my, ka\2x\1dy modu\2l \1loglanowy ma sw\2o\1j \ odpowiedni
\r
1308 modu\2l \1w j\2e\1zyku C. Poniewa\2x \1chcemy przekazywa\2c \1sterowanie pomi\2e\1dzy
\r
1311 takimi modu\2l\1ami w C, wraz z tekstami modu\2lo\1w przet\2l\1umaczony tekst
\r
1314 musi mie\2c \1zdefiniowan\2a \1tablic\2e\1: \,
\r
1320 \4int \1(* module []) () ;
\r
1326 Ka\2x\1da pozycja \ w \ tej \ tablicy \ musi \ okre\2s\1la\2c \ \1modu\2l\1, \ zgodnie \ z
\r
1329 porz\2a\1dkiem zadanym przez tablic\2e \1PROT. Ca\2l\1y program \ ko\2n\1czy \ modu\2l
\r
1332 \1main(), gdzie warto\2s\1ci tej tablicy musz\2a \1by\2c \1tak w\2l\1a\2s\1nie okre\2s\1lone
\r
1335 i \ gdzie \ przekazuje \ si\2e \ \1sterowanie \ do \ \ loglanowego \ \ programu
\r
1374 W \ powy\2x\1szym \ tek\2s\1cie \ A1,...,Ak \ s\2a \ \ \1nazwami \ \ modu\2lo\1w, \ \ kt\2o\1re
\r
1377 wprowadzi\2l \1translator i okre\2s\1laj\2a \1one \ odpowiednie \ modu\2l\1y \ w \ C.
\r
1380 Instrukcja Init() inicjalizuje struktury danych Running \ Systemu.
\r
1383 Potem IC okre\2s\1lamy na 1 i \ przekazujemy \ sterowanie \ do \ programu
\r
1386 loglanowego \ ( \ przekazywanie \ \ sterowania \ \ pomi\2e\1dzy \ \ modu\2l\1ami
\r
1389 zostanie porzedstawione w rozdziale 7). \,
\r
1395 W podobny spos\2o\1b definiuje si\2e \1etykiet\2e \3lastwill \1w module. Atrybut
\r
1398 \3lastwill \1w prototypie musi \ okre\2s\1la\2c \ \1tak\2a \ \1warto\2sc \ \1zmiennej \ IC,
\r
1401 kt\2o\1ra przeka\2x\1e sterowanie w odpowiednie miejsce modu\2l\1u. \,
\r
1416 Plik \ Rsdata.h \ dostarcza \ \ odpowiednich \ \ macro \ \ s\2l\1u\2xa\1cych \ \ do
\r
1419 adresowania zmiennych loglanowych. \ Macro \ Address(\3dnum\1,\3off\1) \ daje
\r
1422 adres zmiennej o numerze displaya \3dnum \1i offsecie \ \3off\1. \ Wykonanie
\r
1425 zatem instrukcji podstawienia: \,
\r
1437 dla \ zmiennych \ integer \ \ o \ \ adresach \ \ (\3dnum\1,\3off\1) \ \ odpowiednio
\r
1440 (1,2),(2,3) oraz (1,4) t\2l\1umaczymy nast\2e\1puj\2a\1co: \,
\r
1446 *Address(1,2)= *Address(2,3) + *Address(1,4);
\r
1452 Plik Rsdata.h daje \ tak\2x\1e \ dwa \ dodatkowe \ macra \ dla \ adresowania
\r
1455 lokalnego i globalnego. Local(\3off\1) daje adres w obiekcie \ aktywnym
\r
1458 o \ offsecie \ \3off\1, \ Global(\3off\1) \ daje \ adres \ w \ obiekcie \ programu
\r
1461 g\2lo\1wnego o offsecie \3off\1. Instrukcj\2e\1:\,
\r
1473 gdzie i jest zmienn\2a \1globaln\2a \1o offsecie \ 5, \ a \ j \ jest \ zmienn\2a
\r
1476 \1lokaln\2a \1o offsecie 2 t\2l\1umaczymy nast\2e\1puj\2a\1co: \,
\r
1482 *Global(5) -= *Local(2);
\r
1488 Wykonywanie operacji arytmetycznych na innym \ typie \ ni\2x \ \1integer
\r
1491 wymaga \ zastosowania \ zmiany \ typu \ (cast). \ Nie \ wiem \ \ jak \ \ w
\r
1494 przysz\2l\1o\2s\1ci post\2a\1pi kompilator z typami pierwotnymi \ r\2ox\1nymi \ od
\r
1497 typu integer, niemniej dla typu real mo\2x\1emy \ w \ spos\2o\1b \ naturalny
\r
1500 dokona\2c \1zmiany kwalifikacji. Plik Rsdata.h zawiera \ odpowiednie
\r
1503 makra \ Fladdress, \ Fllocal \ i \ Flglobal, \ \ kt\2o\1re \ \ automatycznie
\r
1506 dokonuj\2a \1konwersji typu integer na real. Zatem instrukcj\2e\1: \,
\r
1518 dla zmiennych typu real o \ adresach \ odpowiednio \ (2,3) \ i \ (1,4),
\r
1521 t\2l\1umaczymy nast\2e\1puj\2a\1co: \,
\r
1527 *Fladdress(2,3) += *Fladdress(1,4);
\r
1539 Poza \ optymalizacj\2a \ \1adresowania \ \ polegaj\2a\1c\2a \ \ \1na \ \ wywo\2l\1ywaniu
\r
1542 uproszczonych macro (Global i \ Local), \ kompilator \ Loglanu \ mo\2x\1e
\r
1545 stosowa\2c \1zmienne lokalne j\2e\1zyka C. \ Dotyczy \ to \ w \ szczeg\2o\1lno\2s\1ci
\r
1548 zmiennych steruj\2a\1cych p\2e\1tlami, ale tak\2x\1e wielu \ innych \ sytuacji.
\r
1551 (Poniewa\2x \ \1zaproponowana \ tutaj \ wersja \ kompilatora \ nie \ wymaga
\r
1554 generowania \ \ zmiennych \ \ roboczych, \ \ nie \ \ \ widz\2e \ \ \ \1mo\2x\1liwo\2s\1ci
\r
1557 wykorzystania takiej techniki w obliczaniu wyra\2x\1e\2n\1.) \ Przyk\2l\1adowo
\r
1560 w Loglanie p\2e\1tle: \,
\r
1569 \4for \1i:=3 \4to \1n
\r
1575 if \1(p \4mod \1i)=0 \4then \1k:=1; \4exit fi\1;
\r
1584 mo\2x\1emy przet\2l\1umaczy\2c \1nast\2e\1puj\2a\1co (wiedz\2a\1c, \2x\1e k \ jest \ zmienn\2a
\r
1587 \1o adresie (3,4), n jest zmienn\2a \1o adresie (0,1) i wreszcie p
\r
1590 jest zmienn\2a \1o adresie (1,2)): \,
\r
1602 \4for \1(i=3; i<= *Global(1); i++)
\r
1608 \4if \1( *Address(1,2) % i ==0) { *Address(3,4)=1; \4break\1;};
\r
1620 co oczywi\2s\1cie da znacznie lepszy kod ko\2n\1cowy, ni\2x \ \1wersja \ "czysto
\r
1632 *Local(2)=3; /* za\2lox\1my, \2x\1e i ma lokalny offset 2 */
\r
1641 \4if \1( *Local(2) > *Global(1) ) \4break\1;
\r
1644 \4if \1( *Address(1,2) % *Local(2) ==0)
\r
1647 { *Address(3,4)=1; \4break\1; };
\r
1665 Dost\2e\1p \ do \ \ element\2o\1w \ \ tablic \ \ dynamicznych \ \ daje \ \ procedura
\r
1668 Arrayelem(X,i). \ \ Pierwszy \ \ parametr \ \ musi \ \ okre\2s\1la\2c \ \ \1zmienn\2a
\r
1671 \1referencyjn\2a \1wskazuj\2a\1c\2a \1obiekt tablicy natomiast \ drugi \ parametr
\r
1674 musi okre\2s\1la\2c \ \1indeks \ tablicy. \ Przyk\2l\1adowo, \ wczytanie \ tablicy
\r
1677 ca\2l\1kowitej wyznaczonej przez adres (1,2) o zakresie wska\2z\1nika \ od
\r
1680 1 do n, gdzie n ma adres (0,8), mo\2x\1e wygl\2a\1da\2c \1nast\2e\1puj\2a\1co: \,
\r
1689 \4for \1(i=1; i<= *Global(8); i++)
\r
1692 scanf("%d", Arrayelem(*Address(1,2),i));
\r
1704 Natomiast wypisanie takiej tablicy b\2e\1dzie \ r\2o\1wnie \ proste, \ i \ ma
\r
1707 posta\2c \1nast\2e\1puj\2a\1c\2a\1: \,
\r
1716 \4for \1(i=1; i<= *Global(8); i++)
\r
1719 printf("%d", *Arrayelem(*Address(1,2),i));
\r
1728 W celu wykonywania adresowania zdalnego nale\2x\1y wywo\2l\1a\2c \ \1procedur\2e
\r
1731 \1RS o nazwie Physical(X). Parametrem tej procedury jest referencja
\r
1734 do \ obiektu. \ Adres \ wzgl\2e\1dny \ w \ obiekcie \ wyznacza \ translator.
\r
1737 Przyk\2l\1adowo rozwa\2x\1my instrukcj\2e \1i:=X.k, gdzie i ma adres (1,1), X
\r
1740 ma adres (2,3) i wreszcie k ma offset 4. Odpowiednia instrukcja w
\r
1743 j\2e\1zyku C powinna mie\2c \1posta\2c\1: \,
\r
1749 *Address(1,1)= *(Physical(Address(2,3)+4);
\r
1755 RS \ dostarcza \ tak\2x\1e \ wielu \ pomocnych \ \ operacji \ \ na \ \ adresach
\r
1758 wirtualnych. Poza Physical(X) mamy Physimple(X), kt\2o\1ra \ realizuje
\r
1761 wyznaczenie adresu bez sprawdzania zgodno\2s\1ci licznik\2o\1w (mo\2x\1e \ by\2c
\r
1764 \1u\2x\1ywana \ w \ zoptymalizowanych \ wersjach). \ \ Mamy \ \ te\2x \ \ \1operacje
\r
1767 podstawienia referencyjnego Refmove(X<Y) co odpowiada X:=Y. \ Dwie
\r
1770 funkcje \ Member(X) \ i \ Notmember(X) \ daj\2a \ \1odpowiednie \ testy \ na
\r
1773 istnienie \ obiektu. \ Wreszcie \ Equal(X,Y) \ i \ Notequal(X,Y) \ daj\2a
\r
1776 \1por\2o\1wnania \ zmiennych \ referencyjnych, \ co \ odpowiada \ warto\2s\1ciom
\r
1779 wyra\2x\1e\2n \1X=Y i \ X=/=Y. \ Instrukcj\2e \ \1X:=\4none \ \1realizuje \ none(X).
\r
1782 Ponadto wszystkie zmienne referencyjne (nie dotyczy \ to \ adres\2o\1w
\r
1785 po\2s\1rednich) s\2a \1inicjalizowane na \4none\1. Inne zmienne maj\2a \ \1warto\2sc
\r
1788 \1pocz\2a\1tkowa nieokre\2s\1lona. \,
\r
1794 6. Operacje otwierania obiekt\2o\1w
\r
1800 Mamy cztery operacje otwierania obiekt\2o\1w: Openrc, Slopen, Dopen \ i
\r
1803 Open array. Ich nag\2lo\1wki s\2a \1nast\2e\1puj\2a\1ce: \,
\r
1815 \4unsigned int \1*X;
\r
1824 Slopen (\3a\1,X,Y)
\r
1827 \4unsigned int \1*X,*Y;
\r
1839 Dopen(\3a\1,\3b\1,X)
\r
1842 \4int \3a\1,\3b\1;
\r
1845 \4unsigned int \1*X;
\r
1854 Openarray (\3a\1,\3l\1,\3u\1,X)
\r
1857 \4int \3l\1,\3u\1;
\r
1863 \4unsigned int \1*X;
\r
1872 Procedura Openrc otwiera obiekt klasy, \ kt\2o\1ra \ nie \ ma \ kodu \ ani
\r
1875 modu\2lo\1w wewn\2e\1trznych. Slopen otwiera \ obiekt \ ze \ znanym \ ojcem
\r
1878 syntaktycznym \ (dost\2e\1p \ zdalny \ do \ procedury). \ Procedura \ Dopen
\r
1881 otwiera obiekt modu\2l\1u widocznego i wreszcie \ procedura \ Openarray
\r
1884 otwiera \ obiekt \ tablicy. \ Parametr \ X \ jest \ \ adresem \ \ zmiennej
\r
1887 referencyjnej, kt\2o\1ra po wykonaniu odpowiedniej \ procedury \ b\2e\1dzie
\r
1890 wskazywa\2c \1na otwarty \ obiekt. \ Parametr \ \3a \ \1wskazuje \ zawsze \ na
\r
1893 indeks prototypu otwieranego obiektu w tablicy PROT. \,
\r
1899 W procedurze Slopen parametr Y wskazuje na obiekt, kt\2o\1ry \ ma \ by\2c
\r
1902 \1ojcem syntaktycznym otwieranego obiektu. \ W \ procedurze \ Dopen \ \3b
\r
1905 \1jest \ numerem \ prototypu \ w \ kt\2o\1rym \ jest \ zadeklarowany \ \ modu\2l
\r
1908 \1otwierany. W procedurze Openarray parametry \3l\1, \3u \1okre\2s\1laj\2a \1dolny
\r
1911 i g\2o\1rny wska\2z\1nik indeksu. \,
\r
1920 7. Operacje przekazywania sterowania
\r
1926 Wywo\2l\1anie modu\2l\1u loglanowego mo\2x\1e odbywa\2c \ \1si\2e \ \1tylko \ za \ pomoc\2a
\r
1929 \1wywo\2l\1ania odpowiedniego modu\2l\1u w C. Takie wywo\2l\1ania odk\2l\1adane \ na
\r
1932 stos \ powodowa\2l\1yby \ szybkie \ jego \ przepe\2l\1nienie. \ \ Aby \ \ unikn\2ac
\r
1935 \1odk\2l\1adania kopii modu\2lo\1w j\2e\1zyka C na stos mo\2x\1na za \ ka\2x\1dym \ razem
\r
1938 przekazywania sterowania pomi\2e\1dzy \ modu\2l\1ami \ wraca\2c \ \1do \ programu
\r
1941 g\2lo\1wnego main(), czyszcz\2a\1c w ten spos\2o\1b stos. \ Ka\2x\1da \ z \ procedur
\r
1944 przekazywania sterowania pomi\2e\1dzy modu\2l\1ami wyznacza \ tylko \ numer
\r
1947 kolejnego \ modu\2l\1u, \ kt\2o\1ry \ nale\2x\1y \ wywo\2l\1a\2c\1. \ Taki \ numer \ \ modu\2l\1u
\r
1950 b\2e\1dziemy trzyma\2c \1na zmiennej globalnej \3modulenumber\1. W \ programie
\r
1953 main() nale\2x\1y tylko wywo\2l\1a\2c \1odpowiedni modu\2l \1za pomoc\2a \1instrukcji
\r
1956 module[\3modulenumber\1]().\,
\r
1968 Aby powr\2o\1t do programu main() czy\2s\1ci\2l \1stos, \ kt\2o\1ry \ mo\2x\1e \ zawiera\2c
\r
1971 \1poza kolejnym wykonywanym modu\2l\1em wywo\2l\1ania \ r\2ox\1nych \ pomocniczych
\r
1974 procedur, nale\2x\1y skorzysta\2c \1z procedur standardowych \ setjmp \ oraz
\r
1977 longjmp dostarczanych przez system C. Ustawiaj\2a\1c setjmp(buffer) \ w
\r
1980 programie \ g\2lo\1wnym, \ ka\2x\1de \ zako\2n\1czenie \ przekazywania \ sterowania
\r
1983 pomi\2e\1dzy modu\2l\1ami ko\2n\1czy wykonanie longjmp(buffer,-1). \ Sterowanie
\r
1986 wraca do setjmp(buffer) czyszcz\2a\1c \ stos. \ Zako\2n\1czenie \ wykonywania
\r
1989 programu \ mo\2x\1na \ zrealizowa\2c \ \1wywo\2l\1aniem \ \ longjmp(buffer,-2). \ \ W
\r
1992 zale\2x\1no\2s\1ci \ od \ warto\2s\1ci \ setjmp(buffer) \ otrzymanej \ w \ programie
\r
1995 main() mo\2x\1emy albo przekaza\2c \1sterowanie do kolejnego modu\2l\1u, \ albo
\r
1998 zako\2n\1czy\2c \1wykonywanie programu. Przy \ takich \ za\2l\1o\2x\1eniach \ program
\r
2001 g\2lo\1wny ma nast\2e\1puj\2a\1c\2a \1posta\2c\1:\,
\r
2034 \3modulenumber\1=0;\,
\r
2037 \4if \1(setjmp(buffer)!=-2) module[\3modulenumber\1]();\,
\r
2046 W RS mamy \ pi\2ec \ \1operacji \ zwi\2a\1zanych \ z \ prostym \ przekazywaniem
\r
2049 sterowania: \ Go, \ Back, \ Endclass, \ Inn \ oraz \ Endrun. \ Oto \ \ ich
\r
2061 \4unsigned int \1*X;
\r
2094 Procedura \ Go(X) \ przekazuje \ sterowania \ do \ obiektu \ X. \ \ Typowa
\r
2097 kolejno\2sc \ \ \1operacji \ \ przy \ \ przekazywaniu \ \ \ sterowania \ \ \ jest
\r
2100 nast\2e\1puj\2a\1ca: \,
\r
2109 /* przekazanie parametr\2o\1w do X */
\r
2115 Lm:/* po powrocie z X */
\r
2124 Procedura Back() zwraca sterowanie po Dl. Nie \ ma \ parametr\2o\1w. \ W
\r
2127 przypadku wsp\2ol\1program\2o\1w \ musi \ by\2c \ \1po \ niej \ wej\2s\1cie \ opatrzone
\r
2139 Lm:/* ponowna reaktywacja modu\2l\1u */
\r
2145 Procedura \ Endclass() \ realizuje \ operacj\2e \ \ \1zako\2n\1czenia \ \ klasy.
\r
2148 Wywo\2l\1ujemy j\2a \1w miejscu wyst\2a\1pienia ko\2n\1ca klasy (\4return \1w \ klasie
\r
2151 t\2l\1umaczone \ jest \ zawsze \ na \ Back \ ). \ Procedura \ \ ta \ \ sprawdza
\r
2154 dynamicznie w jakiego typu obiekcie jest sterowanie. Je\2x\1eli \ jest
\r
2157 to obiekt wsp\2ol\1programu, wywo\2l\1ywana \ jest \ operacja \ Endcor(). \ W
\r
2160 przeciwnym przypadku \ wywo\2l\1ywana \ jest \ zwyk\2l\1a \ operacja \ Back().
\r
2163 Zako\2n\1czenie \ nieprefiksowanego \ podprogramu \ \ lub \ \ bloku \ \ mo\2x\1na
\r
2166 zrealizowa\2c \1za pomoc\2a \1procedury \ Back(), \ natomiast \ w \ przypadku
\r
2169 klasy \ niemo\2x\1liwe \ jest \ statyczne \ sprawdzenie \ czy \ b\2e\1dzie \ \ to
\r
2172 instrukcja ko\2n\1cz\2a\1ca wsp\2ol\1program, czy te\2x \1nie. \,
\r
2178 Procedura Inn(k) przekazuje sterowanie \ przez \ \4inner\1. \ Warto\2sc \ \1k
\r
2181 okre\2s\1la d\2l\1ugo\2sc l\1a\2n\1cucha prefiksowego danego \ modu\2l\1u. \ Instrukcja
\r
2184 po Inn(k) musi by\2c \1tak\2x\1e w stosowny \ spos\2o\1b \ opatrzona \ etykiet\2a\1.
\r
2187 Powr\2o\1t za \4inner \1wykonuje si\2e \1bezpo\2s\1rednio, bez \ uczestnictwa \ RS.
\r
2190 Na przyk\2l\1ad, maj\2a\1c \ modu\2l\1y \ A \ i \ B \ (B \ prefiksowany \ przez \ A),
\r
2193 operacja \4inner \1w A oraz powr\2o\1t w B powinny wygl\2a\1da\2c \1nast\2e\1puj\2a\1co: \,
\r
2232 \3modulenumber\1=n; /* gdzie n jest numerem modu\2l\1u A */\,
\r
2235 longjmp(buffer,-1); /* skok do programu g\2lo\1wnego */\,
\r
2238 \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ /* gdzie wywo\2l\1any zostanie modu\2l \1A */\,
\r
2247 Procedura Endrun ko\2n\1czy wykonanie programu.
\r
2253 8. Operacje usuwania obiekt\2o\1w
\r
2259 Mamy \ dwie \ procedury \ do \ usuwania \ obiekt\2o\1w \ : \ Killafter() \ i
\r
2262 Gkill(X). Pierwsza z nich wywo\2l\1ywana jest po powrocie z procedury,
\r
2265 funkcji lub \ bloku \ loglanowego. \ Jej \ zadaniem \ jest \ czyszczenie
\r
2268 \2l\1a\2n\1cucha Sl (patrz \ punkt \ 3). \ Zatem \ typowa \ kolejno\2sc \ \1operacji
\r
2271 wywo\2l\1ania takiego modu\2l\1u loglanowego b\2e\1dzie nast\2e\1puj\2a\1ca :\,
\r
2280 /* przekazanie parametr\2o\1w wej\2s\1ciowych */
\r
2286 Lm: /* przekazanie parametr\2o\1w wyj\2s\1ciowych */
\r
2295 Jakkolwiek nowy RS jest wyposa\2x\1ony w \ automatyczny \ od\2s\1miecacz \ i
\r
2298 zb\2e\1dne obiekty funkcji, procedur i blok\2o\1w \ i \ tak \ b\2e\1da \ usuwane,
\r
2301 jednak\2x\1e wywo\2l\1anie Killafter() w przypadku \ ka\2x\1dego \ modu\2l\1u \ typu
\r
2304 procedura, funkcja lub blok usprawni dzia\2l\1anie pami\2e\1ci \ RS, \ gdy\2x
\r
2307 \1najcz\2es\1ciej jest to ostatni obiekt w pami\2e\1ci, \ kt\2o\1rego \ usuni\2e\1cie
\r
2310 odbywa si\2e \1jak na stosie. \,
\r
2316 Operacja Gkill(X) jest star\2a \1operacj\2a \1z modyfikacjami opisanymi \ w
\r
2319 punkcie 3. Parametrem tej operacji jest adres usuwanego obiektu. \,
\r
2331 9. Operacje na wsp\2ol\1programach
\r
2340 RS dostarcza trzech procedur operuj\2a\1cych na wsp\2ol\1programach. S\2a \1to
\r
2343 operacje \ Endcor(), \ Attach(X) \ \ oraz \ \ Attachwith(X,\3signalnum\1,Y).
\r
2346 Operacja Endcor jest wywo\2l\1ywana na zako\2n\1czenie wsp\2ol\1programu. \ Jej
\r
2349 dzia\2l\1anie zosta\2l\1o om\2o\1wione przy okazji \ opisywania \ struktury \ Dl.
\r
2352 Operacja \ Attach(X) \ \ przekazuje \ \ sterowanie \ \ do \ \ wsp\2ol\1programu
\r
2355 wyznaczonego przez parametr X. \,
\r
2361 Wi\2e\1kszego om\2o\1wienia \ wymaga \ natomiast \ operacja \ Attachwith. \ Jej
\r
2364 pierwszym parametrem jest referencja do wsp\2ol\1programu gdzie ma by\2c
\r
2367 \1wywo\2l\1any alarm. Drugi parametr to numer \ sygna\2l\1u. \ Wreszcie \ trzeci
\r
2370 parametr jest referencj\2a \1do obiektu utworzonego \ handlera \ (o \ ile
\r
2373 taki zostanie znaleziony). Po wywo\2l\1aniu mo\2x\1na b\2e\1dzie przekaza\2c \ \1do
\r
2376 handlera parametry wej\2s\1ciowe i dopiero wtedy przekaza\2c \ \1sterowanie
\r
2379 do wsp\2ol\1programu X za \ pomoc\2a \ \1zwyk\2l\1ego \ Attach. \ Ciag \ instrukcji
\r
2382 realizuj\2a\1cych \ wywo\2l\1anie \ sygna\2l\1u \ w \ innym \ wsp\2ol\1programie \ \ mo\2x\1e
\r
2385 wygl\2a\1da\2c \1na przyk\2l\1ad tak: \,
\r
2391 Attachwith(X,s,Y);
\r
2394 /* przekazujemy do Y parametry wej\2s\1ciowe */
\r
2400 Lm: /* dalsze instrukcje w module */
\r
2418 Z \ wyj\2a\1tkami \ \ zwi\2a\1zane \ \ s\2a \ \ \1operacje \ \ Raising(\3signalnum\1,X) \ \ i
\r
2421 Termination() oraz etykiety \3lastwill\1. \,
\r
2427 Operacja Raising(\3signalnum\1,X) powoduje \ poszukiwanie \ w \ aktywnym
\r
2430 \2l\1a\2n\1cuchu Dl handlera dla sygna\2l\1u o numerze \3signalnum\1. Je\2x\1eli taki
\r
2433 handler \ zostanie \ znaleziony, \ otwarty \ zostanie \ jego \ \ obiekt,
\r
2436 kt\2o\1rego referencja przekazana zostanie \ na \ parametr \ X. \ Po \ tej
\r
2439 instrukcji \ mo\2x\1na \ przekaza\2c \ \1do \ \ obiektu \ \ handlera \ \ parametry
\r
2442 wej\2s\1ciowe i wreszcie przekaza\2c \ \1sterowanie \ do \ handlera \ zwyk\2l\1ym
\r
2445 Go(X). Czyli odpowiedni ci\2a\1g instrukcji jest \ taki \ sam \ jak \ dla
\r
2448 wywo\2l\1ania procedury. \ Zamiast \ operacji \ Dopen \ czy \ Slopen \ mamy
\r
2451 operacj\2e \1Raising. Oczywi\2s\1cie po powrocie obiekt \ handlera \ chcemy
\r
2454 usun\2ac\1, musi zatem wyst\2a\1pi\2c \1Killafter(). \,
\r
2463 Je\2x\1eli w handlerze wyst\2e\1puje \ na \ zako\2n\1czenie \ instrukcja \ \4return\1,
\r
2466 wykonuje \ si\2e \ \1zwyk\2l\1e \ Back() \ z \ jego \ konsekwencjami. \ Mamy \ \ do
\r
2469 czynienia ze zwyk\2l\1a procedur\2a \1tylko wo\2l\1an\2a \1dynamicznie. Je\2x\1eli \ na
\r
2472 zako\2n\1czenie \ handlera \ wyst\2e\1puje \ terminate, \ wywo\2l\1ujemy \ operacj\2e
\r
2475 \1Termination(). Jak teraz powinny wygl\2a\1da\2c \ \1odpowiednie \ instrukcj\2e
\r
2478 \1lastwill. Ot\2ox \1Termination ustawia w ka\2x\1dym obiekcie \ \2l\1a\2n\1cucha \ Dl
\r
2481 (od obiektu gdzie wywo\2l\1ano \ alarm \ do \ obiektu \ gdzie \ znaleziono
\r
2484 handler) lokalne sterowanie \ na \ etykiet\2e \ \3lastwill\1. \ Nast\2e\1pnie \ w
\r
2487 handlerze nale\2x\1y wykona\2c \1zwyk\2l\1e \ Back() \ - \ powr\2o\1t \ po \ Dl \ linku.
\r
2490 Pierwsza \ instrukcja \ lastwill \ \ powinna \ \ by\2c \ \ \1zatem \ \ operacj\2a
\r
2493 \1Killafter(). Czyli w handlerze terminate t\2l\1umaczymy na: \,
\r
2508 natomiast ci\2a\1g instrukcji lastwill powinien wygl\2a\1da\2c \1nast\2e\1puj\2a\1co:
\r
2514 Lk: Killafter(); /* Lk etykieta dla IC=k dla lastwill */
\r
2517 .... /* instrukcje lastwill */
\r
2520 Back(); /* lub IC=...; \3modulenumber\1= ...;\,
\r
2523 longjmp(buffer,-1); \,
\r
2526 w przypadku modu\2l\1u prefiksowanego */
\r
2538 11. Za\2la\1czone przyk\2l\1ady
\r
2544 System RS testowa\2l\1em na przyk\2l\1adach napisanych r\2e\1cznie. \ Stara\2l\1em
\r
2547 si\2e \ \1przetestowa\2c \ \1wszystkie \ wa\2x\1ne \ konstrukcje \ \ RS, \ \ a \ \ wi\2e\1c
\r
2550 otwieranie \ obiekt\2o\1w, \ przekazywanie \ sterowania, \ wsp\2ol\1programy,
\r
2553 wyj\2a\1tki, \ tablice \ dynamiczne, \ no \ i \ oczywi\2s\1cie \ od\2s\1miecacz \ \ z
\r
2556 kompaktyfikatorem. Nie \ mog\2l\1em \ przetestowa\2c \ \1tego \ systemu \ zbyt
\r
2559 szczeg\2ol\1owo, gdy\2x \ \1zawiera \ on \ za \ wiele \ elemnt\2o\1w \ trudnych \ do
\r
2562 wychwycenia w r\2e\1cznym tworzeniu kodu. \ Nie \ przetestowa\2l\1em \ wielu
\r
2565 fragment\2o\1w \ zwi\2a\1zanych \ z \ definicj\2a \ \ \1struktur \ \ referencyjnych.
\r
2568 Oczywi\2s\1cie, wydaje \ mi \ si\2e\1, \ \2x\1e \ przetestowanie \ ca\2l\1o\2s\1ci \ nale\2x\1y
\r
2571 od\2l\1o\2x\1y\2c \1do czasu powstania kompilatora. \,
\r
2580 Przyk\2l\1ad perm.c odpowiada znanej nam procedurze \ rekurencyjnej \ na
\r
2583 generowanie wszystkich permutacji. Przyk\2l\1ad ten testuje \ dzia\2l\1anie
\r
2586 otwierania \ obiektu \ widocznego, \ tablice, \ rekursj\2e\1, \ adresowanie
\r
2589 nielokalne i u\2x\1ycie zmiennych sterowania p\2e\1tla. \,
\r
2595 Przyk\2l\1ad merge.c jest stosunkowo du\2x\1ym programem do testowania
\r
2598 operacji na wsp\2ol\1programach. Jest to znany \ program \ na \ scalanie
\r
2601 drzew binarnych poszukiwa\2n\1. \ Program \ testuje \ tak\2x\1e \ wywo\2l\1ywanie
\r
2604 zdalne procedur, przekazywanie parametr\2o\1w referencyjnych, tablice
\r
2607 wsp\2ol\1program\2o\1w, operacje Attach, itp. Napisa\2l\1em przy okazji \ trzy
\r
2610 warianty tego przyk\2l\1adu pozwalaj\2a\1ce \ testowa\2c \ \1inne \ operacje \ na
\r
2613 wsp\2ol\1programach. Ot\2ox \1mergecor.c jest tym samym algorytmem, z tym
\r
2616 \2x\1e \ zako\2n\1czenie \ sygnalizuje \ operacja \ Attachwith \ do \ drugiego
\r
2619 wsp\2ol\1programu. Przyk\2l\1ad testcor.c testuje poprawno\2sc \ \1reakcji \ na
\r
2622 pr\2o\1b\2e \1reaktywacji wsp\2ol\1programu zako\2n\1czonego. Wreszcie \ kmerge.c
\r
2625 jest wariantem tego przyk\2l\1adu gdzie usuwane s\2a \ \1za \ pomoc\2a \ \1Gkill
\r
2628 zb\2e\1dne obiekty. Przyk\2l\1ad ten \ s\2l\1u\2x\1y\2l \ \1przetestowaniu \ poprawno\2s\1ci
\r
2631 dzia\2l\1ania \ \ w\2l\1a\2s\1nie \ \ operacji \ \ Gkill, \ \ tak\2x\1e \ \ w \ \ \ przypadku
\r
2634 wsp\2ol\1program\2o\1w (a to jest przypadek trudniejszy). \,
\r
2643 Program memor.c by\2l \1dla mnie najtrudniejszy w uruchamianiu. Jest
\r
2646 to kr\2o\1tki program na testowanie od\2s\1miecacza i kompaktyfikatora.
\r
2649 Poniewa\2x \1kompaktyfikator musia\2l \ \1by\2c \ \1nieznacznie \ rozszerzony \ z
\r
2652 uwagi na nowa koncepcje Statsl, wprowadzi\2l\1em \ dodatkowy \ przebieg
\r
2655 poprawiaj\2a\1cy to pole dla obiekt\2o\1w, kt\2o\1re po od\2s\1mieceniu pozostan\2a
\r
2658 x\1ywe. Testowa\2l\1em kompaktyfikator dla r\2ox\1nych \ parametr\2o\1w \ w \ tym
\r
2661 przyk\2l\1adzie (n=liczba obiekt\2o\1w wygenerowanych, \ k= \ cz\2e\1stotliwo\2sc
\r
2664 \1usuwania poprzednik\2o\1w). Poniewa\2x \1j\2e\1zyk C \ umo\2x\1liwia \ profilowanie
\r
2667 programu, by\2l\1em \ w \ stanie \ oszacowa\2c \ \1koszt \ wzgl\2e\1dny \ dzia\2l\1ania
\r
2670 kompaktyfikatora. Ot\2ox \1kompaktyfikator zabiera\2l \1nie wi\2e\1cej ni\2x \16
\r
2673 procent czasu dzia\2l\1ania programu , kt\2o\1ry sam nic \ w\2l\1a\2s\1ciwie \ nie
\r
2676 robi. \ Du\2x\1a \ cz\2esc \ \1czasu \ (ponad \ 4 \ procent) \ \ zajmuje \ \ jednak
\r
2679 inicjalizowanie zmiennych referencyjnych. \ Wydaje \ si\2e\1, \ \2x\1e \ taka
\r
2682 inicjalizacja mog\2l\1aby by\2c \ \1czasem \ pomijana \ (programista \ bardzo
\r
2685 rzadko zapomina o podstawieniu \ na \ zmienn\2a \ \1referencyjn\2a\1). \ Przy
\r
2688 okazji tego \ testu \ musz\2e \ \1zwr\2o\1ci\2c \ \1uwag\2e \ \1na \ to, \ \2x\1e \ w \ wersji
\r
2691 loglanowej nowego RS inicjalizacja zmiennych by\2l\1a wykonywana wraz
\r
2694 z zerowanie obiektu (\4none \1=[0,0]). Niestety w wersji napisanej \ w
\r
2697 C chcia\2l\1em, aby zmienne loglanowe \ by\2l\1y \ adresowane \ nie \ poprzez
\r
2700 indeks w tablicy M, ale przez adres w pami\2e\1ci. Takie \ rozwi\2a\1zanie
\r
2703 jest oczywi\2s\1cie bardziej efektywne, ale wymaga innego \ okre\2s\1lenia
\r
2706 \4none\1. Mianowicie \4none\1=[M0,0], gdzie M0= &M[0], oraz M[1]=1. \ Ale
\r
2709 w\2o\1wczas inicjalizacj\2e \1obiektu trzeba wykonywa\2c \1przegl\2a\1daj\2a\1c list\2e
\r
2712 \1referencji \ - \ a \ to \ jak \ widzimy \ kosztuje \ bardzo. \ Co \ prawda
\r
2715 przyk\2l\1adowy \ program \ nie \ zawiera\2l \ x\1adnych \ oblicze\2n\1, \ a \ \ wi\2e\1c
\r
2718 inicjalizacja mog\2l\1a kosztowa\2c \1gros czasu dzia\2l\1ania. \,
\r
2730 Napisa\2l\1em jeden przyk\2l\1ad testuj\2a\1cy \ arytmetyk\2e \ \1zmiennopozycyjn\2a\1.
\r
2733 Jest to program square.c gdzie rozwi\2a\1zujemy r\2o\1wnanie kwadratowe.
\r
2736 Wykorzystuj\2a\1c macra dla arytmetyki \ zmiennopozycyjnej \ bez \ trudu
\r
2739 uda\2l\1o si\2e \1wyrazi\2c \1opracje na typie real. Wida\2c\1, \2x\1e wyra\2x\1enia mog\2a
\r
2742 \1pozosta\2c \1bez zmiany, ewentualne zmienne \ robocze \ wygeneruje \ sam
\r
2745 kompilator j\2e\1zyka C. Ich \ typ \ b\2e\1dzie \ dobrany \ zgodnie \ z \ typem
\r
2748 argument\2o\1w. \,
\r
2757 Przyk\2l\1ad sltest.c s\2l\1u\2x\1y\2l \1do sprawdzenia dzia\2l\1ania nowej struktury
\r
2760 Sl. \ Prosty \ program \ o \ znanej \ strukturze, \ gdzie \ \ wywo\2l\1ywana
\r
2763 procedura ma zniszczone otoczenie \ statyczne, \ pozwala\2l \ \1sprawdzi\2c
\r
2766 \1poprawno\2sc \ \1dzia\2l\1ania \ tej \ techniki. \ Wydaje \ si\2e\1, \ \2x\1e \ \ ma \ \ ona
\r
2769 metodologicznie znaczna przewag\2e \1nad starym rozwi\2a\1zaniem \ (nie \ ma
\r
2772 efekt\2o\1w dziwnych i niezrozumia\2l\1ych \ dla \ programisty), \ a \ ponadto
\r
2775 jest stosunkowo \2l\1atwo implementowalna. Troch\2e \1tracimy \ na \ czasie,
\r
2778 poniewa\2x \1sprawdzenie i czyszczenie \2l\1a\2n\1cuch\2o\1w Sl jest \ dro\2x\1sze \ ni\2x
\r
2781 \1usuwanie na \2s\1lepo obiekt\2o\1w funkcji \ i \ blok\2o\1w. \ Z \ drugiej \ strony
\r
2784 zyskuje si\2e \1troch\2e \1na pami\2e\1ci gdy\2x \1Sl link mo\2x\1e by\2c \1referencj\2a \1bez
\r
2793 Ostatni przyk\2l\1ad functest.c s\2l\1u\2x\1y sprawdzeniu poprawno\2s\1ci u\2x\1ywania
\r
2796 zmiennych podprogramowych. W bloku g\2lo\1wnym zadeklarowany jest \ typ
\r
2799 funkcyjny F oraz funkcja f z parametrem integer oraz typem wyniku
\r
2802 F. W funkcji tej zadeklarowano dwie inne funkcje \ h, \ g, \ kt\2o\1re \ w
\r
2805 tre\2s\1ci funkcji f podstawiane s\2a \1jako jej wynik (typ f jest zgodny
\r
2808 z F). W programie g\2lo\1wnym na zmienne x,y podstawiana jest \ warto\2sc
\r
2811 \1wyniku wywo\2l\1ania funkcji f, dla argumentu 0 tym wynikiem \ jest \ h,
\r
2814 dla argumentu 1 tym wynikiem jest g. Wreszcie \ na \ ko\2n\1cu \ programu
\r
2817 wywo\2l\1ujemy x(n), oraz y(n) jako odpowiednie funkcje zapami\2e\1tane na
\r
2823 \1a#include "rsdata.h"
\r
2828 int IC; /* global control */
\r
2829 int modulenumber; /* module number */
\r
2830 unsigned int *DISPLAY,*DISPDIR; /* displays' addresses */
\r
2831 unsigned int *lastcor,*mycoroutine,*myprocess;
\r
2832 unsigned int *current,*local,*global;
\r
2836 /************************************************************************/
\r
2839 /* Running System basic constants */
\r
2842 /************************************************************************/
\r
2846 #define maxint 65535
\r
2847 #define maxapp maxint /* to be defined for each system */
\r
2848 #define maxcounter (-1) /* maximal value of counter */
\r
2849 #define reflength 2 /* reference variable length */
\r
2850 #define memorylength 16000 /* to be defined for each system */
\r
2851 #define upr (memorylength-1) /* memory upper index */
\r
2852 #define minsize 2 /* minimal object size */
\r
2853 #define virt1 reflength /* auxiliary virtual addresses */
\r
2854 #define virt2 2*reflength
\r
2855 #define virt3 3*reflength
\r
2856 #define virt4 4*reflength
\r
2857 #define virtn virt4
\r
2858 #define lwr (virtn+reflength) /* memory lower index */
\r
2865 /************************************************************************/
\r
2868 /* Functions defining system offsets */
\r
2871 /************************************************************************/
\r
2875 #define Sl(a,am) (am+PROT[a].Sloffset) /* Sl link offset */
\r
2876 #define Dl(a,am) (am+PROT[a].Dloffset) /* Dl link offset */
\r
2877 #define Statsl(a,am) (am+PROT[a].Statoffset) /* Statussl offset */
\r
2878 #define Lsc(a,am) (am+PROT[a].Lscoffset) /* Lsc offset */
\r
2880 /************************************************************************/
\r
2882 /* Sl - defines the static father of an object, where is declared */
\r
2883 /* Dl - defines the dynamic father of an object, where to return */
\r
2884 /* Statussl - defines the number of syntactic sons */
\r
2885 /* Lsc - defines the local sequence control */
\r
2886 /************************************************************************/
\r
2891 /************************************************************************/
\r
2894 /* Running System basic offsets */
\r
2897 /************************************************************************/
\r
2901 /*----------------------------------------------------------------------*/
\r
2903 /*----------------------------------------------------------------------*/
\r
2905 #define lboffset 1 /* array lower bound offset */
\r
2906 #define uboffset 2 /* array upper bound offset */
\r
2907 #define elmoffset 3 /* array first element offset */
\r
2910 /*----------------------------------------------------------------------*/
\r
2911 /* for killed objects */
\r
2912 /*----------------------------------------------------------------------*/
\r
2915 #define shortlink 1 /* offset of next shortlist element */
\r
2916 #define longlink 2 /* offset of next longlist element */
\r
2920 /************************************************************************/
\r
2923 /* Entities imported from a program */
\r
2926 /************************************************************************/
\r
2930 extern int displ,curr,lstcor,chead,displdir; /* basic offsets in main */
\r
2931 extern struct Prototype PROT[]; /* Prototypes */
\r
2932 extern struct Offsets OFF[]; /* Reference structures */
\r
2933 extern struct Elem EL[]; /* Lists of references */
\r
2934 extern struct Hlstelem HL[]; /* Lists of handlers */
\r
2935 extern struct Sgelem SL[]; /* Lists of signals */
\r
2936 extern int perm[],perminv[]; /* Langmaack's permutations */
\r
2937 extern int (*module []) (); /* Modules addresses */
\r
2938 extern int protnum,offnum; /* Length of PROT and OFF */
\r
2939 extern jmp_buf buffer; /* buffer for jumps */
\r
2943 /************************************************************************/
\r
2945 /* Loglan memory structure */
\r
2947 /* M[lwr],...,M[lastused],.....,M[lastitem],...,M[upr] */
\r
2949 /* M[lwr],...,M[lastused] memory for objects */
\r
2950 /* M[lastitem],...,M[upr] memory for indirect addresses */
\r
2952 /*----------------------------------------------------------------------*/
\r
2954 /* Every reference X = [ah,counter] */
\r
2956 /* ah = address in indirect addresses table */
\r
2957 /* counter = a consecutive positive integer */
\r
2959 /* Every indirect addresses table item= [am,guard_counter] */
\r
2961 /* am = address of an object */
\r
2962 /* guard_counter = a consecutive positive integer */
\r
2963 /*----------------------------------------------------------------------*/
\r
2965 /* X=none iff counter <> guard_counter i.e. iff */
\r
2966 /* M[X+1]<> M[M[X]+1] */
\r
2967 /************************************************************************/
\r
2971 unsigned int M[memorylength]; /* Loglan memory */
\r
2972 unsigned int * M0; /* address of M[0],[M0,0]=none */
\r
2974 unsigned int *lastitem,*freeitem;
\r
2976 /* M[lastitem..upr] - indirect addresses table;
\r
2977 M[freeitem] - head of free indirect addresses */
\r
2979 unsigned int *lastused;
\r
2981 /* M[lwr..lastused] - memory for objects */
\r
2986 /************************************************************************/
\r
2989 /* Basic runnning system structures: */
\r
2991 /* class object: */
\r
2992 /* M[lspan],...,M[am],...,M[rspan] */
\r
2993 /* where M[am]=prototype number */
\r
2995 /* array object: */
\r
2996 /* M[am],M[am+1],M[am+2],...,M[am+l-1] */
\r
2997 /* where M[am]=prototype number */
\r
2998 /* M[am+1]= lowr bound */
\r
2999 /* M[am+2]= upper bound */
\r
3000 /* l = total length */
\r
3001 /*----------------------------------------------------------------------*/
\r
3003 /* killed object: */
\r
3004 /* M[am],M[am+1],M[am+2],...,M[am+l-1] */
\r
3005 /* where M[am]=l, total length */
\r
3006 /* M[am+1]= address of next killed */
\r
3007 /* with equal length */
\r
3008 /* M[am+2]= address of next killed */
\r
3009 /* with next greater length */
\r
3011 /************************************************************************/
\r
3018 unsigned int *headk,*headkmin;
\r
3021 /************************************************************************/
\r
3023 /* headk - head of killed objects list */
\r
3024 /* the list ends with M[lwr]=maximal appetite */
\r
3025 /* headkmin - head of killed objects list of minimal length */
\r
3026 /* each list element has only address of next killed with */
\r
3027 /* equal length, so no need for M[am+2] */
\r
3029 /************************************************************************/
\r
3031 /************************************************************************/
\r
3034 /* Global variables */
\r
3037 /************************************************************************/
\r
3043 unsigned int *vipt1,*vipt2,*vipt3,*vipt4,*viptn;
\r
3045 /* vipti = address of M[virti] */
\r
3047 unsigned int *Mlwr,*Mupr; /* addresses of M[lwr] and M[upr] */
\r
3049 int protnum1; /* =protnum+1, used in marking */
\r
3053 /************************************************************************/
\r
3059 /************************************************************************/
\r
3061 static unsigned int Size (a,am)
\r
3065 switch (PROT[a].kind)
\r
3068 return((*(am+uboffset)- *(am+lboffset)+1)*PROT[a].elsize+
\r
3072 return((*(am+uboffset)- *(am+lboffset)+1)*reflength+elmoffset);
\r
3074 return((*(am+uboffset)- *(am+lboffset)+1)*
\r
3075 (OFF[PROT[a].references].size)+elmoffset);
\r
3077 return(*(am+uboffset)- *(am+lboffset)+1+elmoffset);
\r
3079 return(PROT[a].rspan+PROT[a].lspan+1);
\r
3084 /************************************************************************/
\r
3087 /* Position of protnum in object */
\r
3090 /************************************************************************/
\r
3093 static unsigned int Ptposition(a)
\r
3096 switch (PROT[a].kind)
\r
3105 return(PROT[a].lspan);
\r
3112 /************************************************************************/
\r
3115 /* Auxiliary function for dumping the whole memory */
\r
3118 /************************************************************************/
\r
3125 unsigned int *i,*l,*u;
\r
3128 printf("\n SYSTEM VARIABLES\n");
\r
3130 "freeitem lastused lastitem headk headkmin Mlwr Mupr\n");
\r
3131 printf("%3d %3d %3d %3d %3d %3d %3d\n",
\r
3132 freeitem,lastused,lastitem,headk,headkmin,Mlwr,Mupr);
\r
3133 printf(" VIRTUAL ADDRESSES\n");
\r
3137 if (l-18>lastitem) u=l-18;
\r
3140 for (i=l; i>=u; i=i-reflength) printf(" %5d",i);
\r
3141 printf("\n M[ah] ");
\r
3142 for (i=l; i>=u; i=i-reflength) printf(" %5d", *i);
\r
3143 printf("\nM[ah+1]");
\r
3144 for (i=l; i>=u; i=i-reflength) printf(" %5d",*(i+1));
\r
3148 while (u!=lastitem);
\r
3150 printf(" OBJECTS\n");
\r
3152 for (i=M0; i<=lastused; ++i)
\r
3154 printf(" %6d",*i);
\r
3162 } /* end Memorydump */
\r
3166 /************************************************************************/
\r
3169 /* Auxiliary function for dumping prototype structures */
\r
3172 /************************************************************************/
\r
3181 struct Prototype a;
\r
3187 printf("\n PROTOTYPE STRUCTURE\n");
\r
3189 "Nr Kind Lspan Rspan Ref Decl Lev Lstw Sl Dl Lsc Stat Pref Psl \n");
\r
3190 for (i=0; i<=protnum-1; ++i)
\r
3192 printf("\n%2d ",i);
\r
3215 printf("%2d ",a.lspan);
\r
3227 printf(" %2d ",a.rspan);
\r
3228 if (a.references!=-1) printf("%2d ",OFF[a.references].num);
\r
3230 if (a.decl!=-1) printf("%2d ",PROT[a.decl].num) ;
\r
3232 printf("%2d ",a.level);
\r
3233 printf("%2d ",a.lastwill);
\r
3234 printf("%2d %2d %2d %2d ",
\r
3235 a.Sloffset,a.Dloffset,a.Statoffset,a.Lscoffset);
\r
3241 if (a.pref!=-1) printf("%2d ",PROT[a.pref].num) ;
\r
3243 printf("%2d",a.pslength);
\r
3246 printf("\n HANDLERS\n\n handler signals\n");
\r
3247 for (i=0; i<=protnum-1; ++i)
\r
3250 printf("\n%2d ",i);
\r
3264 printf("%2d ",HL[p].hand);
\r
3268 printf("%2d ",SL[q].signalnum);
\r
3275 printf("\n\n OFFSETS\n");
\r
3276 for (i=0; i<=offnum-1; ++i)
\r
3279 printf(" %2d size %d ",i,L.size);
\r
3283 printf(" Listref ");
\r
3285 for (j=1; j<=L.length; ++j)
\r
3287 printf("%2d ",EL[working].offset);
\r
3288 if (EL[working].references==1) printf("s ");
\r
3289 if (EL[working].references==2) printf("p ");
\r
3290 working=EL[working].next;
\r
3294 printf("Segment ");
\r
3295 printf("%2d %2d ",L.start,L.finish);
\r
3296 if (L.head==1) printf(" s ");
\r
3297 if (L.head==2) printf(" p ");
\r
3300 printf("Repeated ");
\r
3301 printf("%2d %2d ",L.ntimes,OFF[L.references].num);
\r
3303 case COMBINEDLIST:
\r
3306 for (j=1; j<=L.length; ++j)
\r
3308 printf("%2d %2d ",EL[working].offset,
\r
3309 OFF[EL[working].references].num);
\r
3310 working=EL[working].next;
\r
3316 printf(" \n PERMUTATIONS ");
\r
3317 printf("\n Prot \tPerm ");
\r
3318 for (i=0; i<=protnum-1; ++i)
\r
3332 printf("\n%2d ",i);
\r
3333 for (j=0; j<=PROT[i].level; ++j)
\r
3334 printf("%2d ",perm[PROT[i].permadd+j]);
\r
3336 printf("\n Prot \tPerminv ");
\r
3337 for (i=0; i<=protnum-1; ++i)
\r
3351 printf("\n%2d ",i);
\r
3352 for (j=0; j<=PROT[i].level; ++j)
\r
3353 printf("%2d ",perminv[PROT[i].permadd+j]);
\r
3356 } /* end writedata */
\r
3360 /************************************************************************/
\r
3363 /* The final address of object referenced by X */
\r
3366 /************************************************************************/
\r
3371 unsigned int *Physical(X)
\r
3374 if( Notmember(X) )
\r
3375 Raising(reftonone,vipt2);
\r
3377 return(Physimple(X));
\r
3382 /************************************************************************/
\r
3384 /* Request for a new object: */
\r
3386 /* (a) Search for a free indirect address item */
\r
3388 /* (i) if freeitem <>0, then take from list of free addresses */
\r
3389 /* (ii) if freeitem=0, then expand indirect addresses table */
\r
3390 /* (iii)if no space, then compactify the whole memory */
\r
3391 /* (iv) if still no space, then fatal error */
\r
3393 /* (b) Search for a frame of size defined by length: */
\r
3395 /* (i) if lastused+length<lastitem, then like in stack */
\r
3396 /* (ii) if no space, then search on the list of killed objects */
\r
3397 /* (iii)if not found, then compactify the whole memory */
\r
3398 /* (iv) if still no space, then fatal error */
\r
3401 /************************************************************************/
\r
3404 static Request(a,length,X)
\r
3406 unsigned int *X,length;
\r
3409 unsigned int *t1,*t2,*t3,*ah,*am,l;
\r
3410 char wascomp,nfound;
\r
3412 if (length >= maxapp)
\r
3415 if (length <= minsize)
\r
3420 /* search for a free indirect address */
\r
3425 freeitem= (unsigned int *)*ah;
\r
3427 else /* extend the indirect address table */
\r
3429 ah=lastitem-reflength;
\r
3434 ah=lastitem-reflength;
\r
3442 /* search for free frame */
\r
3444 t1=lastused+length;
\r
3445 if (t1<lastused || t1>= lastitem)
\r
3447 if(length==minsize && headkmin)
\r
3450 headkmin=(unsigned int *) *(am+shortlink);
\r
3459 if (*(t1)==length ||
\r
3460 *(t1)>(length+minsize) )
\r
3469 t1= (unsigned int *)*(t1+longlink);
\r
3474 if (wascomp) Error(8);
\r
3475 *ah=(unsigned int) freeitem;
\r
3478 ah=lastitem-reflength;
\r
3481 t1=lastused+length;
\r
3482 if (t1<lastused || t1>=lastitem) Error(8);
\r
3488 t3= (unsigned int *) *(t1+shortlink);
\r
3491 *(t3+longlink)= *(t1+longlink);
\r
3493 t3= (unsigned int *)*(t1+longlink);
\r
3495 *(t2+longlink)= (unsigned int) t3;
\r
3512 *X= (unsigned int)ah;
\r
3514 am+=Ptposition(a);
\r
3516 *ah= (unsigned int )am;
\r
3518 } /* end Request */
\r
3524 /************************************************************************/
\r
3527 /* Dispose the object referenced by X=[ah,counter] */
\r
3529 /* (a) dispose the indirect address: */
\r
3530 /* (i) advance M[ah+1], i.e. guard_counter */
\r
3531 /* (ii) if guard_counter=-1, then leave it */
\r
3532 /* for compactification of the whole memory */
\r
3533 /* (iii) otherwise put on the list of free addresses */
\r
3535 /* (b) dispose the frame: */
\r
3536 /* (i) if the frame is bordering free space, increase lastused */
\r
3537 /* (ii) otherwise put it on the list of killed objects */
\r
3538 /* (iii) correct Statussl for procedure closures */
\r
3541 /************************************************************************/
\r
3548 unsigned int *am,*ah;
\r
3549 unsigned int length;
\r
3551 if (Notmember(X)) return;
\r
3553 ah= (unsigned int *) *X;
\r
3554 am= (unsigned int *) *ah;
\r
3555 if (++(*(ah+1))!=maxcounter)
\r
3557 *ah=(unsigned int)freeitem;
\r
3562 length=Size(a,am);
\r
3563 if (am+length-Ptposition(a)-1==lastused)
\r
3567 am-=Ptposition(a);
\r
3575 /************************************************************************/
\r
3578 /* Move virtual address Y on X */
\r
3581 /************************************************************************/
\r
3585 unsigned int *X,*Y;
\r
3594 /************************************************************************/
\r
3597 /* Move procedure closure address Y on X */
\r
3600 /************************************************************************/
\r
3604 unsigned int *X,*Y;
\r
3606 { unsigned int *am;
\r
3613 (*Statsl(a,am))--;
\r
3619 (*Statsl(a,am))++;
\r
3626 /************************************************************************/
\r
3629 /* For Y shortaddress, reconstruct reference on X */
\r
3632 /************************************************************************/
\r
3635 unsigned int *X,*Y;
\r
3638 *(X+1)= *((unsigned int *)*X+1);
\r
3643 /************************************************************************/
\r
3649 /************************************************************************/
\r
3656 *X++ = (unsigned int)M0;
\r
3661 /************************************************************************/
\r
3667 /************************************************************************/
\r
3670 unsigned int *X,*Y;
\r
3673 if (Notmember(X)) return(Member(Y));
\r
3678 return((int)(Physimple(X)-Physimple(Y)));
\r
3682 /************************************************************************/
\r
3688 /************************************************************************/
\r
3692 unsigned int *X,*Y;
\r
3695 return(! Notequal(X,Y));
\r
3699 /************************************************************************/
\r
3702 /* Insert the frame pointed by am on the list of killed objects */
\r
3705 /************************************************************************/
\r
3711 unsigned int *t1,*t2;
\r
3717 *(am+shortlink)=(unsigned int)headkmin;
\r
3729 *(am+shortlink)= *(t1+shortlink);
\r
3730 *(t1+shortlink)= (unsigned int)am;
\r
3736 *(am+longlink)= (unsigned int)t1;
\r
3737 *(am+shortlink)=0;
\r
3738 if(t2) *(t2+longlink)=(unsigned int)am;
\r
3745 t1=(unsigned int *) *(t1+longlink);
\r
3749 } /* end Insert */
\r
3754 /************************************************************************/
\r
3757 /* Purge the Sl-chain of an object referenced by vipt3 */
\r
3759 /* (i) if Statussl=0 and it is procedure instance, dispose it */
\r
3760 /* (ii) otherwise goto end */
\r
3761 /* (iv) put vipt3 = Sl father of vipt3, and goto (i) */
\r
3764 /************************************************************************/
\r
3775 am=Physimple(vipt3);
\r
3777 if ( *Statsl(a,am)) return;
\r
3778 switch (PROT[a].kind)
\r
3785 if ( Physimple(vipt3)!=Physimple(Dl(a,am))) return;
\r
3786 Refset(vipt2,Sl(a,am));
\r
3788 Refmove(vipt3,vipt2);
\r
3790 } /* end of killer */
\r
3794 /************************************************************************/
\r
3797 /* Purge memory after procedure instance termination */
\r
3799 /* (i) if Statussl<>0, nothing can be deallocated */
\r
3800 /* (ii) otherwise dispose the object, put on vipt3 its Sl father */
\r
3801 /* and call Killer, which purges Sl-chain */
\r
3804 /************************************************************************/
\r
3812 am=Physimple(vipt2);
\r
3814 if ( *Statsl(a,am)) return;
\r
3815 Refset(vipt3,Sl(a,am));
\r
3822 /************************************************************************/
\r
3825 /* Compactifier - the play in 9 acts (Oh My God!!!) */
\r
3827 /* It's like an ancient tragedy with prolog, epilogue, */
\r
3828 /* chorus singing in some entr'acts, deus ex machina etc. */
\r
3831 /************************************************************************/
\r
3833 /*----------------------------------------------------------------------*/
\r
3834 /* Procedure traverse is a Deus ex machina */
\r
3835 /* (helps to solve dramatic problems in many moments): */
\r
3837 /* short trip through the object pointed by am with action */
\r
3838 /* performed for each reference */
\r
3839 /* (uses procedures pointed and correct) */
\r
3841 /*----------------------------------------------------------------------*/
\r
3843 static traverse (am,action)
\r
3850 if ((int) *am >= 0) a= *am;
\r
3851 else a= *am+protnum1;
\r
3852 switch (PROT[a].kind)
\r
3854 case PRIMITARRAY :
\r
3857 for (t= am+elmoffset;t<=am+Size(a,am)-1;t+=reflength)
\r
3858 correct(t,action,0);
\r
3861 for (t= am+elmoffset;t<=am+Size(a,am)-1;t+=reflength)
\r
3862 correct(t,action,2);
\r
3864 case STRUCTARRAY :
\r
3865 L=PROT[a].references;
\r
3866 for (t= am+elmoffset;t<=am+Size(a,am)-1;t+=OFF[L].size)
\r
3867 pointed(t,L,action);
\r
3870 for (t= am+elmoffset;t<=am+Size(a,am)-1; t++)
\r
3871 correct(t,action,1);
\r
3874 L=PROT[a].references;
\r
3875 pointed(am,L,action);
\r
3877 } /* end traverse */
\r
3882 /*----------------------------------------------------------------------*/
\r
3884 /* correct all references defined by the structure of offsets L */
\r
3885 /* according to action, in the subframe starting with acron */
\r
3887 /*----------------------------------------------------------------------*/
\r
3889 static pointed (acron,L,action)
\r
3890 unsigned int *acron;
\r
3892 char action; /* 1 nonefy,2 relocate,3 mark,4 Setnone,5 decstatussl */
\r
3894 int i,k,working,ref;
\r
3896 if (L==-1) return;
\r
3897 switch (OFF[L].kind)
\r
3900 working=OFF[L].head;
\r
3901 for (i=1; i<=OFF[L].length; ++i)
\r
3903 k=EL[working].offset;
\r
3904 correct(acron+k,action,EL[working].references);
\r
3905 working=EL[working].next;
\r
3909 switch(OFF[L].head)
\r
3911 for (k=OFF[L].start;k<=OFF[L].finish;k+=reflength)
\r
3912 correct(acron+k,action,0);
\r
3915 for (k=OFF[L].start;k<=OFF[L].finish;++k)
\r
3916 correct(acron+k,action,1);
\r
3919 for (k=OFF[L].start;k<=OFF[L].finish;k+=reflength)
\r
3920 correct(acron+k,action,2);
\r
3926 for (i=1;i<=OFF[L].ntimes;++i)
\r
3928 pointed(acron,OFF[L].references,action);
\r
3929 acron+=OFF[L].size;
\r
3932 case COMBINEDLIST:
\r
3933 working=OFF[L].head;
\r
3934 for (i=1;i<=OFF[L].length;++i)
\r
3936 k=EL[working].offset;
\r
3937 ref=EL[working].references;
\r
3938 pointed(acron+k,ref,action);
\r
3939 working=EL[working].next;
\r
3943 } /* end pointed */
\r
3950 /*----------------------------------------------------------------------*/
\r
3952 /* correct one reference pointed by am according to action */
\r
3953 /* (for long references it is different than for the short ones) */
\r
3955 /*----------------------------------------------------------------------*/
\r
3957 static correct (am,action,reftype)
\r
3959 char reftype; /* 0-fulladdress, 1-shortaddress, 2-procedure closure */
\r
3966 if (reftype==0) nonefy(am); return;
\r
3968 if (reftype==0) relocate(am); else relocs(am);
\r
3971 if (reftype==0) mark(am); else marks(am);
\r
3974 if (reftype==0) Setnone(am); else *am=0;
\r
3979 if ( *am==0) return;
\r
3982 if (a < 0) a+=protnum1;
\r
3983 (*Statsl(a,am))--;
\r
3992 /*----------------------------------------------------------------------*/
\r
3994 /* Two auxiliary procedures mark and marks are called by traverse */
\r
3995 /* in prologue. They help to visit all accessible objects from an */
\r
3996 /* active one. Each accessible object is marked by changing its */
\r
3997 /* basic item M[am](=prototype number) on a negative value. Mark */
\r
3998 /* passes through full references [ah,counter],while marks passes */
\r
3999 /* through simplified references [ah]. */
\r
4001 /*----------------------------------------------------------------------*/
\r
4008 if (Notmember(am)) return;
\r
4010 if ((int) *am >=0)
\r
4023 if (*am==0) return;
\r
4035 /*----------------------------------------------------------------------*/
\r
4038 /* marking of all accessible objects */
\r
4040 /*----------------------------------------------------------------------*/
\r
4043 static prologue ()
\r
4047 am=Physimple(current);
\r
4055 /*----------------------------------------------------------------------*/
\r
4057 /* Chorus song No 1: */
\r
4058 /* for each free address change its guard counter on max */
\r
4060 /*----------------------------------------------------------------------*/
\r
4063 static chorus_song_1 ()
\r
4069 *(t+1)=maxcounter;
\r
4070 t= (unsigned int *) *t;
\r
4076 /*----------------------------------------------------------------------*/
\r
4079 /* for each not-killed object recognize those which */
\r
4080 /* will be deallocated because are not accessible; */
\r
4081 /* knowing that these objects will be deallocated */
\r
4082 /* correct the corresponding Statussl items. */
\r
4084 /*----------------------------------------------------------------------*/
\r
4089 unsigned int *t1,*t2;
\r
4092 for (t2= lastitem;t2<= Mupr;t2+=reflength)
\r
4094 if(*(t2+1)==maxcounter) continue;
\r
4095 t1= (unsigned int *) *t2;
\r
4096 if ((int) *t1 >=0) traverse(t1,5);
\r
4103 /*----------------------------------------------------------------------*/
\r
4106 /* each non-accesible object put on the list of killed */
\r
4107 /* objects; for each accessible object put on M[am] ah */
\r
4108 /* in order to be able in act4 to compute on M[ah] */
\r
4109 /* updated am (Attention! for Ptposition=0,special case) */
\r
4111 /*----------------------------------------------------------------------*/
\r
4117 unsigned int *t1,*t2,*t3,l;
\r
4120 for (t1=lastitem;t1<= Mupr;t1+=reflength)
\r
4122 if (*(t1+1)==maxcounter) continue;
\r
4123 t2= (unsigned int *) *t1;
\r
4124 if ((int) *t2<0) *t2 += protnum1;
\r
4127 *(t1+1)=maxcounter;
\r
4130 t2-=Ptposition(a);
\r
4136 if (Ptposition(a))
\r
4138 t3=t2-Ptposition(a);
\r
4141 *t2= (unsigned int)t1;
\r
4146 *(t2+1)= (unsigned int) t1;
\r
4157 /*----------------------------------------------------------------------*/
\r
4159 /* Chorus song No 2: */
\r
4160 /* marking of all killed objects */
\r
4162 /*----------------------------------------------------------------------*/
\r
4165 #define skilled (-1) /* marking for killed object */
\r
4167 static chorus_song_2 ()
\r
4169 unsigned int *t1,*t2,*t3;
\r
4174 t2=(unsigned int *) *(t1+shortlink);
\r
4175 *(t1+shortlink)=minsize;
\r
4185 t3= (unsigned int *)*(t2+shortlink);
\r
4186 *(t2+shortlink)= *t2;
\r
4190 t1= (unsigned int *) *(t1+longlink);
\r
4197 /*----------------------------------------------------------------------*/
\r
4199 /* Auxiliary procedure nonefy called by traverse. It sets to none */
\r
4200 /* [M0,0] each reference which points no object. */
\r
4202 /*----------------------------------------------------------------------*/
\r
4204 static nonefy (am)
\r
4207 if ( Notmember(am)) Setnone(am);
\r
4212 /*----------------------------------------------------------------------*/
\r
4215 /* traverse memory and for all alive objects set to [M0,0] */
\r
4216 /* each reference pointing no object */
\r
4218 /*----------------------------------------------------------------------*/
\r
4222 unsigned int *t1,*t2,*t3,l;
\r
4226 while (t1<=lastused)
\r
4228 if ( *t1!=skilled)
\r
4231 if (Ptposition(a))
\r
4233 t2=t1+Ptposition(a);
\r
4234 t3= (unsigned int *)*t2;
\r
4240 t3= (unsigned int *) *(t1+1);
\r
4246 if (Ptposition(a))
\r
4248 *t2= (unsigned int) t3;
\r
4252 *(t1+1)= (unsigned int)t3;
\r
4256 t1+= *(t1+shortlink);
\r
4258 for (t1=vipt1; t1<=viptn; t1+=reflength) nonefy(t1);
\r
4263 /*----------------------------------------------------------------------*/
\r
4265 /* Chorus song No 3: */
\r
4266 /* compute new values of indirect addresses and put them */
\r
4267 /* on guard counters; this enables to update references */
\r
4268 /* during memory squeezing; now M[ah+1]= future ah */
\r
4270 /*----------------------------------------------------------------------*/
\r
4272 static chorus_song_3()
\r
4274 unsigned int *t1,*t2;
\r
4277 for ( t2= Mupr; t2>= lastitem; t2-=reflength)
\r
4279 if (*t2==maxcounter) *t2= (unsigned int)M0;
\r
4282 *t2= (unsigned int)t1;
\r
4290 /*----------------------------------------------------------------------*/
\r
4292 /* Two auxiliary procedures relocate and relocs are used in act4. */
\r
4293 /* They update for each reference its ah taking a new one from */
\r
4294 /* M[ah+1] computed in chorus song No 3. Procedure relocates is */
\r
4295 /* applied for full references, procedure relocs for simplified. */
\r
4297 /*----------------------------------------------------------------------*/
\r
4299 static relocate(am)
\r
4302 *am= *( (unsigned int *)*am+1);
\r
4309 if (*am==0) return;
\r
4310 *am= *( (unsigned int *)*am+1);
\r
4315 /*----------------------------------------------------------------------*/
\r
4318 /* squeeze memory; for all alive objects update all */
\r
4319 /* references using traverse with relocate and relocs; */
\r
4320 /* simultaneously update M[ah] with a new value of am */
\r
4321 /* obtained after squeezing memory; reconstruct also */
\r
4322 /* the value of M[am] changed in act2. */
\r
4325 /*----------------------------------------------------------------------*/
\r
4329 unsigned int *t1,*t2,*t3,*t4,*t5,l,k;
\r
4334 while (t1<=lastused)
\r
4336 if (*t1==skilled) t1+= *(t1+shortlink);
\r
4339 t5=(unsigned int *) *t1;
\r
4341 t3=t1+Ptposition(a);
\r
4342 if (Ptposition(a))
\r
4344 t4= (unsigned int *)*t3;
\r
4345 *t3=(unsigned int)t5;
\r
4350 t4= (unsigned int *)*(t1+1);
\r
4355 for (k=1;k<=l;++k)
\r
4357 t5=t2+Ptposition(a);
\r
4358 *t4= (unsigned int)t5;
\r
4363 for (t1=vipt1;t1<=viptn; t1+=reflength) relocate(t1);
\r
4370 /*----------------------------------------------------------------------*/
\r
4373 /* squeeze the indirect address table;update also some */
\r
4374 /* Running System variables. */
\r
4376 /*----------------------------------------------------------------------*/
\r
4379 static epilogue () /* update virtual addresses */
\r
4381 unsigned int *t1,*t2,*t3;
\r
4384 for ( t3= Mupr-1; t3>=lastitem; t3-=reflength)
\r
4386 t2= (unsigned int *)*(t3+1);
\r
4396 Update(current); /* update DISPDIR */
\r
4397 local=Physimple(current); /* update local register */
\r
4401 /*----------------------------------------------------------------------*/
\r
4403 /* Compactify (call prepared procedures) */
\r
4405 /*----------------------------------------------------------------------*/
\r
4411 nlength=lastitem-lastused;
\r
4421 printf("\n Compactifier used; released space=%d\n",
\r
4422 lastitem-lastused-nlength);
\r
4427 /*----------------------------------------------------------------------*/
\r
4429 /* Errors at run-time are handled by Error(n), where n is */
\r
4430 /* the error number. */
\r
4432 /*----------------------------------------------------------------------*/
\r
4448 printf("\nReference to none\n");
\r
4449 longjmp(buffer,-2);
\r
4451 printf("\nIllegal attach\n");
\r
4452 longjmp(buffer,-2);
\r
4454 printf("\nCoroutine terminated\n");
\r
4455 longjmp(buffer,-2);
\r
4457 printf("\nImproper coroutine end\n");
\r
4458 longjmp(buffer,-2);
\r
4460 printf("\nIncorrect kill\n");
\r
4461 longjmp(buffer,-2);
\r
4463 printf("\nArray index error\n");
\r
4464 longjmp(buffer,-2);
\r
4466 printf("\nIllegal array generation\n");
\r
4467 longjmp(buffer,-2);
\r
4469 printf("\nMemory overflow\n");
\r
4470 longjmp(buffer,-2);
\r
4472 printf("\nend of a program execution\n");
\r
4473 longjmp(buffer,-2);
\r
4475 printf("\nhandler not found\n");
\r
4476 longjmp(buffer,-2);
\r
4482 /*----------------------------------------------------------------------*/
\r
4485 /* opens a new object of a class without system attributes */
\r
4486 /* a - prototype number, */
\r
4487 /* X - reference to the opened object */
\r
4489 /*----------------------------------------------------------------------*/
\r
4498 Request(a,Size(a,0),X);
\r
4506 /*----------------------------------------------------------------------*/
\r
4509 /* opens a new object of with explicitly given Sl-father */
\r
4510 /* a - prototype number, */
\r
4511 /* X - reference to the opened object */
\r
4512 /* Y - reference to its Sl-father */
\r
4514 /*----------------------------------------------------------------------*/
\r
4520 unsigned int *X,*Y;
\r
4524 unsigned int *am,*Slr,*Dlr;
\r
4526 Request(a,Size(a,0),X);
\r
4536 (*Statsl(a,am))++;
\r
4541 /*----------------------------------------------------------------------*/
\r
4544 /* opens a new object of a visible module */
\r
4545 /* a - prototype number, */
\r
4546 /* b - prototype number of a's static father */
\r
4547 /* X - reference to the opened object */
\r
4549 /*----------------------------------------------------------------------*/
\r
4560 Slopen(a,X,DISPLAY+reflength*perm[PROT[b].permadd+PROT[c].level]);
\r
4565 /*----------------------------------------------------------------------*/
\r
4568 /* opens a new array */
\r
4569 /* a - prototype number, */
\r
4570 /* l - lower bound */
\r
4571 /* u - upper bound */
\r
4572 /* X - reference to the opened object */
\r
4574 /*----------------------------------------------------------------------*/
\r
4576 Openarray (a,l,u,X)
\r
4583 unsigned int length;
\r
4586 if (u<l) Raising(illarray,vipt2);
\r
4588 switch (PROT[a].kind)
\r
4590 case PRIMITARRAY :
\r
4591 length=length*PROT[a].elsize ;
\r
4595 length=length*reflength;
\r
4597 case STRUCTARRAY :
\r
4598 length=length*(OFF[PROT[a].references].size);
\r
4603 length+=elmoffset;
\r
4604 Request(a,length,X);
\r
4613 /*----------------------------------------------------------------------*/
\r
4616 /* calls an object X */
\r
4617 /* X - reference to the object */
\r
4619 /*----------------------------------------------------------------------*/
\r
4628 *(Lsc(a,local))=IC*protnum1+modulenumber;
\r
4630 Refmove(current,X);
\r
4631 local=Physimple(X);
\r
4634 switch (PROT[a].kind)
\r
4641 switch (PROT[a].kind)
\r
4653 longjmp(buffer,-1);
\r
4658 /*----------------------------------------------------------------------*/
\r
4661 /* explicit return statement */
\r
4662 /* used also in end of unprefixed subprogram or block */
\r
4664 /*----------------------------------------------------------------------*/
\r
4669 unsigned int *Dlr;
\r
4674 if (*Dlr==0) Endcor();
\r
4675 Refmove(vipt2,current);
\r
4676 *Lsc(a,local)=IC*protnum1+modulenumber;
\r
4677 Refset(current,Dlr);
\r
4680 local=Physimple(current);
\r
4682 IC= *Lsc(a,local);
\r
4683 modulenumber=IC%protnum1;
\r
4685 longjmp(buffer,-1);
\r
4690 /*----------------------------------------------------------------------*/
\r
4693 /* end of class statement */
\r
4695 /*----------------------------------------------------------------------*/
\r
4702 switch (PROT[a].kind)
\r
4705 case SUBROUTINE: Back(); break;
\r
4706 case COROUTINE: Endcor(); break;
\r
4720 /*----------------------------------------------------------------------*/
\r
4723 /* passes control to a subclass */
\r
4724 /* k - class level in the inheritance sequence */
\r
4726 /*----------------------------------------------------------------------*/
\r
4734 if (PROT[a].pslength==k) return;
\r
4735 for (t=2; t<=PROT[a].pslength-k; ++t) a=PROT[a].pref;
\r
4738 longjmp(buffer,-1);
\r
4744 /*----------------------------------------------------------------------*/
\r
4747 /* end of computations */
\r
4749 /*----------------------------------------------------------------------*/
\r
4760 /*----------------------------------------------------------------------*/
\r
4763 /* update display algorithm; no way to explain how it */
\r
4764 /* works without a special theoretical background. */
\r
4765 /* X - reference to an object which will be active */
\r
4767 /*----------------------------------------------------------------------*/
\r
4774 int a,c,d,j,k,permadd,l;
\r
4781 permadd=PROT[a].permadd;
\r
4784 l=perm[permadd+k];
\r
4785 Refset(DISPLAY+reflength*l,X);
\r
4786 *(DISPDIR+l)= (unsigned int )am;
\r
4787 if (k--==0) return;
\r
4788 j=perminv[PROT[a].permadd+perm[PROT[d].permadd+k]];
\r
4796 j=perminv[PROT[a].permadd+perm[PROT[c].permadd+j]];
\r
4798 while (PROT[a].level-j);
\r
4800 } /* end of update */
\r
4805 /*----------------------------------------------------------------------*/
\r
4808 /* deallocates a class, an array or a coroutine object */
\r
4809 /* for coroutines deallocates the whole cycle */
\r
4810 /* X - reference to the object */
\r
4812 /*----------------------------------------------------------------------*/
\r
4817 unsigned int *am,*Dlr;
\r
4820 if (Notmember(X) ) return;
\r
4823 switch (PROT[a].kind)
\r
4834 if ( *Statsl(a,am)) Raising(incorkill,vipt2);
\r
4835 Refset(vipt3,Sl(a,am));
\r
4844 Refset(vipt4,Dlr);
\r
4845 if ( *Statsl(a,am)) Raising(incorkill,vipt2);
\r
4847 if (Physimple(X)==Physimple(Dlr)) break;
\r
4848 am=Physimple(Dlr);
\r
4855 am=Physimple(vipt2);
\r
4858 Refset(vipt3,Dlr);
\r
4860 Refmove(vipt4,vipt2);
\r
4861 Refmove(vipt2,vipt3);
\r
4863 while (Notequal(vipt2,X));
\r
4868 Refset(vipt3,Sl(a,am));
\r
4869 Refset(vipt4,Dl(a,am));
\r
4874 while (Member(X));
\r
4877 Raising(incorkill,vipt2);
\r
4884 /*----------------------------------------------------------------------*/
\r
4887 /* end of coroutine; it is different than return; */
\r
4888 /* treated as an error */
\r
4889 /*----------------------------------------------------------------------*/
\r
4896 if (Member(lastcor))
\r
4898 Attachwith(lastcor,imprterm,vipt2);
\r
4904 Attachwith(myprocess,imprterm,vipt2);
\r
4906 Attach(myprocess);
\r
4912 /*----------------------------------------------------------------------*/
\r
4915 /* auxiliary for Attach and Attachwith */
\r
4916 /* X - reference to a coroutine */
\r
4918 /*----------------------------------------------------------------------*/
\r
4924 unsigned int *amnew,*amold,*Dlr;
\r
4927 if ( Notmember(X)) Raising(ilattach,vipt2);
\r
4928 amnew=Physimple(X);
\r
4930 switch(PROT[a].kind)
\r
4936 Raising(ilattach,vipt2);
\r
4938 if ( *Lsc(a,amnew)<protnum1) Raising(corterm,vipt2);
\r
4939 if (Equal(mycoroutine,X)) return;
\r
4940 Refmove(vipt2,mycoroutine);
\r
4941 amold=Physimple(mycoroutine);
\r
4944 Refmove(mycoroutine,X);
\r
4946 Refmove(lastcor,vipt2);
\r
4950 *Lsc(a,local)=IC*protnum1+modulenumber;
\r
4952 Refset(current,Dlr);
\r
4954 local=Physimple(current);
\r
4956 IC= *Lsc(a,local);
\r
4957 } /*end Atthhelp */
\r
4961 /*----------------------------------------------------------------------*/
\r
4964 /* attaches coroutine X */
\r
4965 /* X - reference to a coroutine */
\r
4967 /*----------------------------------------------------------------------*/
\r
4973 modulenumber=IC%protnum1;
\r
4975 longjmp(buffer,-1);
\r
4982 /*----------------------------------------------------------------------*/
\r
4985 /* raises a signal */
\r
4986 /* signalnum- signal number, */
\r
4987 /* X - reference to the opened object */
\r
4989 /*----------------------------------------------------------------------*/
\r
4992 Raising(signalnum,X)
\r
4996 unsigned int *am,*Y;
\r
5004 switch (PROT[a].kind)
\r
5013 h=PROT[b].handlist;
\r
5016 if (PROT[HL[h].hand].others &&
\r
5017 signalnum<=syssigl)
\r
5019 Slopen(HL[h].hand,X,Y);
\r
5025 if (SL[s].signalnum==signalnum)
\r
5027 Slopen(HL[h].hand,X,Y);
\r
5038 if (signalnum<=syssigl)
\r
5040 else Error(10); /* handler not found */
\r
5041 } /* end Raising */
\r
5046 /*----------------------------------------------------------------------*/
\r
5049 /* raises a signal in another coroutine */
\r
5050 /* signalnum - signal number, */
\r
5051 /* X - reference to the coroutine */
\r
5052 /* Y - reference to the opened object */
\r
5054 /*----------------------------------------------------------------------*/
\r
5057 Attachwith(X,signalnum,Y)
\r
5058 unsigned int *X,*Y;
\r
5063 Refmove(vipt3,mycoroutine);
\r
5065 Raising(signalnum,Y);
\r
5067 Refmove(current,Y);
\r
5068 local=Physimple(current);
\r
5074 /*----------------------------------------------------------------------*/
\r
5076 /* Termination: */
\r
5077 /* terminates an active dynamic chain */
\r
5079 /*----------------------------------------------------------------------*/
\r
5084 unsigned int *X,*Y,*am;
\r
5095 *Lsc(b,Y)=PROT[b].lastwill*protnum1+b;
\r
5096 if (Y==am) return;
\r
5104 /*----------------------------------------------------------------------*/
\r
5107 /* initialize all RS data */
\r
5109 /*----------------------------------------------------------------------*/
\r
5116 protnum1=protnum+1;
\r
5119 M[1]= (unsigned int) M0;
\r
5123 viptn=vipt4= &M[virt4];
\r
5133 Request(0,Size(0,0),vipt1);
\r
5134 global=local=Physimple(vipt1);
\r
5135 *Statsl(0,local)=0;
\r
5136 traverse(local,4);
\r
5137 DISPLAY= local+displ;
\r
5138 current= local+curr;
\r
5139 Refmove(current,vipt1);
\r
5140 Refmove(DISPLAY,current);
\r
5141 DISPDIR= local +displdir;
\r
5142 *DISPDIR = (unsigned int) local;
\r
5143 lastcor= local+lstcor;
\r
5144 mycoroutine= local+chead;
\r
5145 Refmove(mycoroutine,current);
\r
5152 /*----------------------------------------------------------------------*/
\r
5155 /* compute final address of an array element */
\r
5156 /* X - reference to the array object */
\r
5157 /* i - element index */
\r
5159 /*----------------------------------------------------------------------*/
\r
5162 unsigned int *Arrayelem (X,i)
\r
5167 unsigned int *am,length;
\r
5171 if (i> (int) *(am+uboffset)) Raising(arrayind,vipt2);
\r
5172 i-= (int) *(am+lboffset);
\r
5173 if (i<0) Raising(arrayind,vipt2);
\r
5174 switch (PROT[a].kind)
\r
5177 length=PROT[a].elsize;
\r
5184 length=OFF[PROT[a].references].size;
\r
5190 am+=elmoffset+length*i;
\r
5196 #include <setjmp.h>
\r
5197 /* on-line functions */
\r
5200 #define Physimple(X) (unsigned int *)(* ((unsigned int *) *X))
\r
5201 #define Notmember(X) ( *(X+1)!= *((unsigned int *)*X+1) )
\r
5202 #define Member(X) ( *(X+1)== *((unsigned int *)*X+1) )
\r
5204 #define Address(dnum,off) ((unsigned int *)*(DISPDIR+dnum)+off)
\r
5205 #define Local(off) (local+off)
\r
5206 #define Global(off) (global+off)
\r
5207 #define Fladdress(dnum,off) (float *) ((unsigned int *)*(DISPDIR+dnum)+off)
\r
5208 #define Fllocal(off) (float *)(local+off)
\r
5209 #define Flglobal(off) (float *)(global+off)
\r
5212 /* repeated headings */
\r
5214 unsigned int * Arrayelem();
\r
5215 unsigned int * Physical();
\r
5218 /* global common variables */
\r
5221 /* constants for standard signals */
\r
5224 #define syssigl 100
\r
5225 #define reftonone 1
\r
5226 #define ilattach 2
\r
5228 #define imprterm 4
\r
5229 #define incorkill 5
\r
5230 #define arrayind 6
\r
5231 #define illarray 7
\r
5234 /* common structures */
\r
5236 enum { CLASS,SUBROUTINE,PROCESS,COROUTINE,HANDLER,RECORD,
\r
5237 PRIMITARRAY,REFARRAY,SUBARRAY,STRUCTARRAY,POINTARRAY};
\r
5242 int kind; /* prototype kind */
\r
5243 int num; /* numer of prototype */
\r
5244 int lspan,rspan; /* lspan for arrays = elsize */
\r
5245 int references; /* address of reference structure */
\r
5246 int decl,level; /* sl-father and depth in sl-tree */
\r
5247 int lastwill; /* label for lastwill statements */
\r
5248 int permadd; /* address of permutations */
\r
5249 int Sloffset,Dloffset; /* offsets of */
\r
5250 int Statoffset,Lscoffset; /* system attributes */
\r
5251 int handlist; /* handlerlist for handlers=others */
\r
5252 int pref,pslength; /* address of pref father, prefix */
\r
5253 /* sequence length, both */
\r
5254 /* for handlers not existant */
\r
5258 #define elsize lspan
\r
5259 #define others handlist
\r
5262 /* Structure for handlers */
\r
5266 int hand; /* handler prototype */
\r
5267 int signlist; /* address of signals */
\r
5273 int signalnum; /* signal number */
\r
5282 /* Structure for offsets of reference variables in objects */
\r
5288 int offset; /* offset in a structure */
\r
5289 int next; /* next list element */
\r
5290 int references; /* for COMBINEDLIST points */
\r
5291 /* the corresponding substructure */
\r
5292 /* for SIMPLELIST */
\r
5293 /* 0 when it is fulladdress */
\r
5294 /* 1 when it is shortaddress */
\r
5295 /* 2 when it is procedure closure */
\r
5300 enum { SIMPLELIST,SEGMENT,REPEATED,COMBINEDLIST}; /* kind of structure */
\r
5304 int kind; /* kind as above */
\r
5305 int size; /* size of characterized object */
\r
5306 int num; /* reference structure number */
\r
5307 int length,finish; /* for SIMPLELIST and COMBINEDLIST */
\r
5308 /* length is a list length, finish not used */
\r
5309 /* for SEGMENT length (start) and finish */
\r
5310 /* define a segment span */
\r
5311 /* for REPEATED length=ntimes */
\r
5312 /* finish not used */
\r
5313 int head; /* for LISTS it is a list head */
\r
5315 /* 0 when they are fulladdresses */
\r
5316 /* 1 when they are shortaddresses */
\r
5317 /* 2 when they are procedure closures */
\r
5318 /* for REPEATED not used */
\r
5319 int references; /* address of reference structure */
\r
5320 /* used only for REPEATED */
\r
5323 #define start length
\r
5324 #define ntimes length
\r