Как BASIC находит неправильный оператор NEXT, когда тело цикла пропускается

9

Установите машину WABAC , Шерман. Этот вопрос касается BASIC в целом и Microsoft BASIC-80 в частности. Старая школа базовая. С номерами строк.

Как (или, вернее, сделали) интерпретаторы старой школы BASIC обрабатывают циклы FOR ... NEXT, когда тело цикла не было выполнено, а оператор NEXT появился не в порядке?

СЛЕДУЮЩИЙ оператор СЛЕДУЮЩЕГО от предшествующего времени:

Вот подпрограмма из игры Awari из «101 основных компьютерных игр» Дэвида Х. Аля :

200 K=M:GOSUB 600
205 E=0:IF K>6 THEN K=K-7
210 C=C+1:IF C<9 THEN F(N)=F(N)*6+K
215 FOR I=0 TO 5:IF B(I)<>0 THEN 230
220 NEXT I
225 RETURN
230 FOR I=7 TO 12:IF B(I)<>0 THEN E=1:RETURN
235 GOTO 220

и вот он со всем, кроме отредактированного управления потоком:

200 GOSUB 600
215 FOR I=0 TO 5:IF ... THEN 230
220 NEXT I
225 RETURN
230 FOR I=7 TO 12:IF ... THEN RETURN
235 GOTO 220

Это возвращает не такие уж приятные воспоминания? Вы слышите, как Дейкстра перекатывается в могиле?

Вот интересная часть того, что происходит в этом фрагменте:

  • Второй цикл FOR, поскольку он использует ту же переменную цикла, заменяет первый цикл FOR
  • Два цикла FOR используют один и тот же оператор NEXT
  • Оператор NEXT второго цикла FOR идет перед ним, в порядке исходного кода, но после него, в порядке выполнения.

Тогда вы можете предположить, что интерпретатор, запустив цикл FOR, просто запускает операторы, пока это не произойдет через цикл NEXT. Порядок утверждения в источнике в этом случае не имеет значения. Но давайте посмотрим, что говорит руководство basic80 о циклах FOR:

В руководстве basic-80 написано "му ..."

Тело цикла пропускается, если начальное значение цикла, умноженное на знак шага, превышает окончательное значение, умноженное на знак шага.

Таким образом, тело цикла может быть полностью пропущено.

У нас есть доказательства в виде опубликованных программ, что, по крайней мере, некоторые версии BASIC динамически находили свои СЛЕДУЮЩИЕ операторы. Это достаточно легко сделать, когда выполняется тело цикла. Однако в случае, когда тело оператора FOR должно быть пропущено, как позволяет BASIC-80, как BASIC обнаружил оператор NEXT, учитывая, что он может быть перед оператором FOR в исходном порядке?

  • Версия BASIC, используемая в «101 Basic Computer Games», всегда выполняла тело цикла хотя бы один раз?
  • Требуется ли для BASIC-80 оператор NEXT цикла FOR после оператора FOR в исходном порядке?

PS: Да, я пишу переводчик BASIC для старой школы BASIC. Это болезнь.

Уэйн Конрад
источник
Книга Ahl была первоначально опубликована DEC в 1973 году, предшествовавшей Microsoft BASIC на два года. Программы, вероятно, были бы сделаны в RT-11 BASIC или BASIC-PLUS. Помимо системных расширений, большинство диалектов были совместимы, и я запустил программы из DEC-версии книги на нескольких системах без особых трудностей или вообще без них. Вы можете найти разобранные, документированные источники ознакомления с Applesoft BASIC ROM. Код, который реализует NEXTоператор, начинается с $ DCF9.
Blrfl
Не знаю насчет BASIC-80, но я на 100% уверен, что Commodore Basic (который был Microsoft BASIC V2) всегда выполняет цикл один раз, и порядок операторов в источнике не имеет значения - как вы и подозреваете.
Док Браун

Ответы:

7

Это возвращает старые времена ...

У меня есть копия книги, 3-е издание, 1975 год. Я проверил ваш список, и он не оригинален. В исходном исходном коде операторы не имеют пробелов, а присваивания имеют ключевое слово LET. Например

200 LETK=M:GOSUB600

Диалект - ЦИФРОВОЙ БАЗОВЫЙ PDP-11 (не Basic-plus или BASIC-80). По опыту, не все эти игры работали на всех диалектах бейсика. У меня есть смутное воспоминание о необходимости перекодировать некоторые из этих игр, чтобы заставить их работать на других диалектах. Этот вид ужасной петлевой структуры определенно был проблемой.

У меня был опыт работы с более чем 20 различными диалектами бейсика, и я могу сказать вам, что это был спорный вопрос в то время. Было 2 основных лагеря.

В одном лагере были полные переводчики, которые анализировали каждую строку заново каждый раз, когда ее видели. Они обрабатывали цикл FOR, помещая его в стек, идентифицируемый его переменной, а затем сканируя стек на совпадение с каждым NEXT. Если они пропустили цикл, им пришлось бы сканировать источник на СЛЕДУЮЩИЙ. Некоторые сделали, некоторые нет.

Другим лагерем были токенизаторы или полукомпиляторы. Они будут сканировать все строки перед выполнением и конвертировать их в какой-то внутренний формат. Они также сопоставляли циклы FOR / NEXT и проверяли на отсутствие целей GOTO и GOSUB. Насколько я помню, DEC и BASIC-80 были в этом лагере, но это давно.

В ответ на ваши вопросы,

  1. Да, диалект BASIC пропускает цикл, если изначально удовлетворен
  2. Нет, последовательность FOR NEXT не была задокументированным требованием, но поведение было неопределенным. Как профессионал, очевидно, я никогда этого не делал. :)

Надеюсь это поможет. Это ужасные языки, но если ты должен это сделать ...

david.pfx
источник
Это очень полезно, спасибо. Книга имеет версию DEC, версию TRS-80 и версию микрокомпьютера. Программы в версии микрокомпьютера основаны на Microsoft 8080 basic (MITS Altair Basic Rev 4.0); это цель моего переводчика.
Уэйн Конрад
Я использовал MBASIC на CP / M примерно в 1980 году, но ни на одной из этих ранних машин для любителей. Вам нужна файловая система! Во многих отношениях я считаю реинкарнацию DEC / DG / HP / CAI / Prime / Interdata / Tektronix Basic более интересной, но я понимаю, почему вы этого не можете. Удачи! Свяжитесь со мной, если я могу помочь.
david.pfx
2

У меня нет копии спецификации для одного из этих древних интерпретаторов BASIC передо мной (она может даже не существовать), но я собираюсь выйти на конечность и сказать, что интерпретатор BASIC не выполнит ДАЛЕЕ в цикле FOR, который не принадлежит ему, даже если переменная цикла имеет то же имя.

Итак, другими словами, в вашем примере

200 K=M:GOSUB 600
205 E=0:IF K>6 THEN K=K-7
210 C=C+1:IF C<9 THEN F(N)=F(N)*6+K
215 FOR I=0 TO 5:IF B(I)<>0 THEN 230
220 NEXT I
225 RETURN
230 FOR I=7 TO 12:IF B(I)<>0 THEN E=1:RETURN
235 GOTO 220

когда строка 235 выполняется и переходит к строке 220, строка 220 СЛЕДУЕТ СЛЕДУЕТ верхней петле FOR, а не нижней.

Это видно по сообщению об ошибке «NEXT без FOR»; интерпретатор BASIC отклоняет любой NEXT, для которого он не нашел соответствующего FOR. Как правило, это происходит, когда вы выходите из строя вашего СЛЕДУЮЩЕГО, как в

100 FOR I = 1 to 10
110 FOR J = 1 to 10
120 ...
130 NEXT I
140 NEXT J

Итак, чтобы ответить на ваши маркированные вопросы:

  • Да, если переменная цикла находится в пределах диапазона FOR.
  • Да, насколько мне известно, это так.
Роберт Харви
источник
2
«интерпретатор BASIC не будет выполнять NEXT в цикле FOR, который ему не принадлежит» - я знаю по крайней мере одну семью старых интерпретаторов BASIC, где это утверждение неверно, вы не можете обобщить это для «всех древних интерпретаторов BASIC».
Док Браун
Спецификация существует. Поиск БДПХ-11 БЕЙСИК.
david.pfx
1
Спасибо, что ответили на этот странный вопрос. Теперь я подтвердил, что BASIC, используемый в книге, при обнаружении второго оператора FOR, имеющего ту же переменную counter, забывает о первом операторе FOR и перезапускает цикл из второго. Это противоречит твоему удару в темноте. Это одиозный способ писать циклы, но BASIC в любом случае - вонючий материал.
Уэйн Конрад
2

Что делает Бейсик "101 Компьютер Игры"

Диалект BASIC, используемый в микрокомпьютерной версии «101 Computer Games», будет выполнять тело цикла FOR ... NEXT хотя бы один раз. Это отличается от BASIC-80 v. 5 .

Из с. i12 , перечисление исключений для "обычного" бейсика:

FOR ... TO ... STEP

Как и в стандартном BASIC, за исключением того, что тест на завершение цикла выполняется после того, как он был выполнен. То есть когда эта программа запущена:

10 FOR X=2 TO 1
20 PRINT "HI"
30 NEXT X
40 END

«Привет» будет напечатан ...

Из-за этого у этого диалекта BASIC нет проблем с поиском оператора NEXT или совместного использования того же следующего оператора с несколькими операторами FOR. Статический анализ не требуется. Просто выполните каждый оператор, как он происходит, и вы в конечном итоге получите оператор NEXT, где бы он ни находился.

Возможно ли для BASIC-80 справиться с неисправным СЛЕДУЮЩИМ?

Оператор FOR может пропустить тело цикла, как позволяет BASIC-80 v.5, и в большинстве случаев по-прежнему допускает неупорядоченные операторы NEXT. Вот как:

  • Интерпретатор получает два состояния: «работает» и «переход к следующему»
  • Находясь в состоянии «выполнение», интерпретатор выполняет каждый оператор в обычном режиме.
  • При оценке оператора FOR, если тело цикла должно быть пропущено, состояние изменяется на «переход к следующему»
  • В состоянии «переход к следующему» интерпретатор пропускает все операторы, кроме NEXT и безусловного GOTO.
    • Безусловный оператор GOTO сопровождается
    • Оператор NEXT, если его переменная совпадает с оператором FOR (или если переменная не указана), переключается обратно в состояние «выполняется». Если переменная не совпадает, интерпретатор остается в состоянии «переход к следующему».

Это будет обрабатывать простые патологические последовательности, такие как в вопросе. Он не будет обрабатывать случаи, когда СЛЕДУЮЩИЙ достигнут оператором IF ... GOTO или GOSUB. Код, который делает это, намного хуже, чем и без того плохой код в вопросе, поэтому просто объявить, что интерпретатор не будет поддерживать такие случаи, не является необоснованным. Для переводчика может быть даже допустимо поджечь такой код.

Уэйн Конрад
источник