Отлов исключений из цикла

Я пытаюсь написать слово 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? Или, что я делаю неправильно здесь?


person beeflobill    schedule 05.11.2014    source источник


Ответы (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 ;

or

: clear   begin depth while drop repeat ;

or

: clear   sp0 sp! ;
person Lars Brinkhoff    schedule 05.11.2014