Мы привыкли делать это в Форт. Когда я знаю, что слово будет возвращаться к слову, которое будет возвращаться, мы извлекаем адрес возврата из стека, а затем возвращаемся, фактически возвращаясь к вызывающей стороне вызываемого. Оно работает.
аю свой собственный интерпретируемый язык, похожий на Lisp, и хочу оптимизировать хвостовой вызов. Я хочу освободить мой интерпретатор из стека C, чтобы я мог управлять своими собственными переходами от функции к функции и своей магией стека для достижения TCO. (Я на самом деле не имею в виду отсутствие стека как такового, просто тот факт, что вызовы не добавляют фреймы в стек C. Я хотел бы использовать свой собственный стек, который не увеличивается при использовании хвостовых вызовов). Как Stackless Python, и в отличие от Ruby или ... стандартного Python, я думаю.
Но, поскольку мой язык является производным от Лиспа, все вычисления s-выражений в настоящее время выполняются рекурсивно (потому что это самый очевидный способ, которым я думал сделать этот нелинейный, высоко иерархический процесс). У меня есть функция eval, которая вызывает функцию Lambda :: apply каждый раз, когда сталкивается с вызовом функции. Затем функция apply вызывает eval для выполнения тела функции и т. Д. Взаимная голодная не хвостовая C рекурсия. Единственная итеративная часть, которую я сейчас использую, - это оценка тела последовательных s-выражений.
(defun f (x y)
(a x y)) ; tail call! goto instead of call.
; (do not grow the stack, keep return addr)
(defun a (x y)
(+ x y))
; ...
(print (f 1 2)) ; how does the return work here? how does it know it's supposed to
; return the value here to be used by print, and how does it know
; how to continue execution here??
Итак, как мне избежать использования C рекурсии? Или я могу использовать какое-то goto, которое перепрыгивает через функции c? longjmp, возможно? Я действительно не знаю. Пожалуйста, потерпите меня, я в основном сам (интернет) преподаю в программировании.