У меня уже давно созрело решение данной проблемы, которое попробую здесь описать.
Предисловие.
Ничего принципиально нового, всё это нам известно, просто взглянем, как следует
Из структурного программирования мы привыкли к древовидной декомпозиции действий.
Например, есть действие A. Очень крупное.
Его определение даётся в терминах нескольких действий помельче: A = A1 A2 A3.
Далее A1, A2, A3 определяются аналогичным образом.
Есть и другой способ декомпозиции действий, кроме такого древовидного. Назовём его списочным. (Лисперам он сразу напомнит CAR-CDR
).
При определении большого действия A мы сначала указываем действия на мелком уровне детализации, а потом некое крупное, которое является продолжением этих мелких:
A = o1 o2 A1.
A1 = o3 o4 A2.
A2 = ...
Часто начинающие пытаются составлять алгоритмы именно в таком стиле, за что "бывают биты" - ведь для императивного языка такие вызовы связаны с углублением в стек (а потенциально и с рекурсией, если циклическое продолжение).
Однако, объективно, такой стиль декомпозиции действий для многих задач вполне естественный. Мы привыкли к такой декомпозиции из БНФ-грамматик. Антони Хоар в своей книге "Последовательные взаимодействующие процессы" вводит формализм для описания процессов также именно с таким стилем декомпозиции.
Ну и, наконец, для функционального программирования такой стиль вполне привычен. Например, конечные автоматы программируются часто именно так. Почему нет проблем? Потому что функциональные компиляторы понимают, что вызов концевой, и оптимизируют его просто до перехода на следующую процедуру (если есть параметры, то с замещением на стеке).
----
Собственно, вот вам и "культурный GOTO", хоть для конечных автоматов, хоть для какой-то сложной структуры процессов. Это - концевой вызов процедуры, который бы распознавался компилятором - и это распознавание бы гарантировалось.
Однако, следуя идеологии Оберона "всё явно", стоит ввести отдельный оператор, в пару к RETURN.
Назвать, например, CONTINUE.
CONTINUE Proc(params) - прекращает выполнение текущей процедуры, снимая её кадр со стека, и вызывает Proc(params).
Если наша процедура является функцией, то Proc тоже должна быть функцией соответствующего типа.