Jakie są dobre sposoby wdrożenia eliminacji połączeń ogonowych?

Napisałem mały interpreter schematu w bezbożnej mieszance C / C++, ale muszę jeszcze zaimplementować odpowiednie wywołania ogonowe.

Znam klasyczny algorytm MTA, ale czy są inne ładne sposoby implementacji tego? Wiem, że mógłbym umieścić stos programu na stercie, ale nadal nie byłoby to właściwe wyeliminowanie, jak mówi standard, należy obsługiwać nieograniczoną liczbę aktywnych wywołań ogonowych.

Ja też bawiłem się longjmps, ale jak na razie myślę, że będzie to działać dobrze tylko dla nie-wzajemnych rekurencyjnych wywołań ogonowych.

W Jaki Sposób główne systemy oparte na C implementują właściwą rekurencję ogonową?

Author: csl, 2011-05-14

3 answers

Prostsze niż pisanie kompilatora i maszyny Wirtualnej jest rejestracja i trampolina interpretera. Ponieważ masz interpreter, a nie kompilator (zakładam), potrzebujesz tylko kilku prostych przekształceń, aby uzyskać odpowiednie wsparcie dla wywołań ogonowych.

Będziesz musiał najpierw napisać wszystko w stylu kontynuowania-przechodzenia, co może być dziwne myśleć i robić w C / C++. Dan Friedman ' s ParentheC samouczek przeprowadzi Cię przez przekształcenie rekurencyjnego, wysokiego poziomu program do postaci, która jest maszynowo tłumaczona na C.

W końcu zaimplementujesz prostą maszynę wirtualną, w której zamiast zwykłych wywołań funkcji wykonasz eval, applyProc itp., przekazujesz argumenty ustawiając zmienne globalne, a następnie wykonujesz goto do następnego argumentu (lub używasz pętli najwyższego poziomu i licznika programu)...

return applyProc(rator, rand)

Staje się

reg_rator = rator
reg_rand = rand
reg_pc = applyProc
return

Oznacza to, że wszystkie funkcje, które normalnie wywołują się rekurencyjnie, są zredukowane do pseudo-assembly, w którym są tylko bloki kodu, które się nie powtarzają. Pętla najwyższego poziomu steruje programem:

for(;;) {
  switch(reg_pc) {
    case EVAL:
      eval();
      break;
    case APPLY_PROC:
      applyProc();
      break;
    ...
  }
}

Edit: przeszedłem przez ten sam proces dla mojego hobby Scheme interpreter, napisany w JavaScript. Skorzystałem z wielu anonimowych procedur, ale może to pomóc jako konkretne odniesienie. Zobacz też foxscheme ' s commit history od 2011-03-13 (30707a0432563ce1632a) do 2011-03-15 (5dd3b521dac582507086 ).

Edit^2: Rekurencja bez ogona będzie zużywać pamięć, nawet jeśli nie będzie jej w stosie.

 10
Author: erjiang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-15 01:56:32

Nie wiedząc, co masz, powiedziałbym, że najprostszym (i najbardziej pouczającym) sposobem na to jest zaimplementowanie kompilatora scheme i maszyny Wirtualnej z "trzech modeli implementacji dla Scheme" Dybvig.
Zrobiłem to tutaj w Javascript (Kopia PDF Dybviga też tam jest): https://github.com/z5h/zb-lisp

Sprawdź src / kompilator.js: kompilatory i implementacja "kodów op" w src/vm.js

 4
Author: z5h,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-14 20:44:40

Jeśli interesują Cię techniki implementacji tłumaczy, tam nie sposób obejść książki" LiSP - Lisp w małych kawałkach " autorstwa Christiana Queinneca. Bardzo dokładnie wyjaśnia wszystkie aspekty wdrażania systemu Scheme z kompletny kod. To wspaniała książka.

Http://www.amazon.com/exec/obidos/ASIN/0521562473/qid=945541473/sr=1-2/002-2995245-1849825

Ale nie zapomnij sprawdzić gazet na ReadScheme.org.

The sekcja

Technologia kompilatora / techniki implementacji i optymalizacji http://library.readscheme.org/page8.html

Ma sporo artykułów na temat optymalizacji połączeń ogonowych.

Między innymi znajdziesz link do tezy Dybviga (klasyka), co jest bardzo dobrze napisane. Wyjaśnia i motywuje wszystko w w bardzo jasny sposób.

 4
Author: soegaard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-15 10:59:43