Nie jest możliwe wdrożenie semantyki wywołań funkcji bez użycia jakiegoś stosu. Można grać tylko w gry słowne (np. Użyj innej nazwy, np. „Bufor powrotu FILO”).
Można użyć czegoś, co nie implementuje semantyki wywołań funkcji (np. Styl przekazywania kontynuacji, aktorzy), a następnie zbudować na niej semantykę wywołań funkcji; ale oznacza to dodanie pewnego rodzaju struktury danych, aby śledzić, gdzie kontrola jest przekazywana, gdy funkcja powraca, a ta struktura danych byłaby rodzajem stosu (lub stosu o innej nazwie / opisie).
Wyobraź sobie, że masz wiele funkcji, które mogą się nawzajem wywoływać. W czasie wykonywania każda funkcja musi wiedzieć, do którego miejsca powrócić, gdy funkcja wyjdzie. Jeśli first
dzwonisz second
, masz:
second returns to somewhere in first
Następnie, jeśli masz second
połączenia third
:
third returns to somewhere in second
second returns to somewhere in first
Następnie, jeśli masz third
połączenia fourth
:
fourth returns to somewhere in third
third returns to somewhere in second
second returns to somewhere in first
Gdy wywoływana jest każda funkcja, gdzieś trzeba przechowywać więcej informacji „gdzie zwrócić”.
Jeśli funkcja zwraca, wówczas używana jest informacja „gdzie zwrócić” i nie jest już potrzebna. Na przykład, jeśli fourth
wróci gdzieś, third
wówczas ilość informacji „gdzie wrócić do” wyniesie:
third returns to somewhere in second
second returns to somewhere in first
Gruntownie; „semantyka wywołania funkcji” oznacza, że:
- musisz mieć informację „gdzie zwrócić”
- ilość informacji rośnie wraz z wywoływaniem funkcji i jest zmniejszana, gdy funkcje powracają
- pierwsza przechowywana informacja „gdzie zwrócić” będzie ostatnią odrzuconą informacją „gdzie zwrócić”
Opisuje bufor lub stos FILO / LIFO.
Jeśli spróbujesz użyć typu drzewa, to każdy węzeł w drzewie nigdy nie będzie miał więcej niż jednego dziecka. Uwaga: węzeł z wieloma potomkami może się zdarzyć tylko wtedy, gdy funkcja wywołuje 2 lub więcej funkcji jednocześnie , co wymaga pewnego rodzaju współbieżności (np. Wątków, fork () itp.) I nie byłby to „semantyka wywołania funkcji”. Jeśli każdy węzeł w drzewie nigdy nie będzie miał więcej niż jednego dziecka; wtedy to „drzewo” byłoby używane tylko jako bufor FILO / LIFO lub stos; a ponieważ jest używany tylko jako bufor FILO / LIFO lub stos, można śmiało twierdzić, że „drzewo” to stos (a jedyną różnicą są gry słowne i / lub szczegóły implementacji).
To samo dotyczy każdej innej struktury danych, która mogłaby być prawdopodobnie zastosowana do zaimplementowania „semantyki wywołania funkcji” - będzie używana jako stos (a jedyną różnicą są gry słowne i / lub szczegóły implementacji); chyba że łamie „semantykę wywołania funkcji”. Uwaga: gdybym mógł, podałbym przykłady innych struktur danych, ale nie mogę wymyślić żadnej innej struktury, która byłaby nieco prawdopodobna.
Oczywiście sposób implementacji stosu jest szczegółem implementacji. Może to być obszar pamięci (gdzie śledzisz „aktualny stos”), może to być jakaś połączona lista (gdzie śledzisz „aktualny wpis na liście”) lub może być zaimplementowany w niektórych inny sposób. Nie ma również znaczenia, czy sprzęt ma wbudowane wsparcie, czy nie.
Uwaga: Jeśli w danym momencie może być aktywne tylko jedno wywołanie dowolnej procedury; możesz statycznie przydzielić miejsce na informacje „gdzie wrócić”. To wciąż stos (np. Połączona lista statycznie przydzielonych wpisów używanych w sposób FILO / LIFO).
Zauważ również, że niektóre rzeczy nie są zgodne z „semantyką wywołań funkcji”. Te rzeczy obejmują „potencjalnie bardzo różną semantykę” (np. Przekazywanie kontynuacji, model aktora); a także obejmuje popularne rozszerzenia „semantyki wywołań funkcji”, takie jak współbieżność (wątki, włókna itp.), setjmp
/ longjmp
, obsługa wyjątków itp.