Ловля исключений из цикла

Я пытаюсь написать слово Forth, которое бросит все элементы в стеке. Я использую довольно тупой метод, выполняя бесконечный цикл с помощью drop и ловя ошибку, когда не удается выполнить drop, поскольку стек пуст.

Мои слова определены так:

( Infinite drop loop)
: droploop begin drop true while drop repeat ;

( Experimental catch with a single drop)
: dropcatcher ['] drop catch drop ;

( Like dropcatcher, but with 'droploop' instead of 'drop')
: dropall  ['] droploop catch drop ;

Когда я запускаю droploop, я получаю сообщение об ошибке, как и ожидалось, и после выполнения стек пуст. Когда я запускаю dropcatcher, он сбрасывается, если стек не пуст, а если стек пуст, он ничего не сообщает. Когда я запускаю dropall, я получаю все остальное в стеке.

Это выглядит так:

2 3 4 5 6 7 8 9 10 dropall.s <9> -1 3 -1 5 -1 7 -1 9 -1 ок

Я ожидаю, что dropall просто очистит стек без жалоб, потому что droploop и dropcatcher, похоже, работают сами по себе, но, увы, я не понимаю, почему dropall не работает.

Почему dropall работает иначе, чем droploop и dropcatcher? Или что я тут не так делаю?

1 ответ

Решение

Когда droploop выдает ошибку, скорее всего это вызовет ABORT или же -1 THROW, который по определению очищает стек данных. Так что вполне может быть, что droploop не удаляет нужное количество элементов стека до обнаружения ошибки, но системный обработчик исключений делает это за вас.

Когда я бегу droploop Сам он либо вылетает, либо зависает. Казалось бы, это подтверждает мою теорию, что существует серьезный недостаток стека.

Что касается состояния стека после dropall я думаю, что gforth, возможно, не обнаружит переполнение стека в нужное время, а то, что вы видите, это какой-то полуслучайный мусор. Следовательно, это то, что droploop оставляет в стеке перед вызовом ABORT,

Примечание: ваш droploop отбрасывает два элемента стека за каждую итерацию, что может или не может быть тем, что вы хотели. Также используйте again для бесконечного цикла вместо true while , Т.е. : droploop begin drop again;

Конечно, лучший способ очистить стек

: clear   depth 0 ?do drop loop ;

или же

: clear   begin depth while drop repeat ;

или же

: clear   sp0 sp! ;
Другие вопросы по тегам