Як BASIC знаходить нестандартний оператор NEXT, коли пропущено тіло циклу


9

Встановіть машину WABAC , Шерман. Це питання стосується BASIC взагалі та зокрема BASIC-80 Microsoft . Стара школа основна. З номерами рядків.

Як (або, скоріше, зробили) старі школи інтерпретатори BASIC поводяться ДЛЯ ... СЛУХАЛЬНИХ циклів, коли тіло циклу не виконується, а оператор NEXT з'явився з ладу?

NEXT-повідомлення, що не вийшло з попереднього часу:

Ось підпрограма з гри " Авари з Девіда Х. Аха" "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 оператор
  • Наступний оператор циклу FOR NEXT надходить до нього, у вихідному порядку, але після нього, у порядку виконання

Ви можете припустити, що інтерпретатор, запустивши цикл FOR, просто запускає оператори, поки це не відбудеться через цикл NEXT. Порядок висловлювання у джерелі в цьому випадку не має значення. Але давайте подивимось, що посібник basic80 повинен сказати про петлі FOR:

У посібнику з базових 80 написано "му ..."

Тіло циклу пропускається, якщо початкове значення циклу, кратне знаку кроку, перевищує кінцеве значення, кратне знаку кроку.

Отже, тіло петлі можна пропустити цілком.

Ми маємо докази у формі опублікованих програм про те, що принаймні деякі версії BASIC динамічно розміщували свої наступні заяви. Це досить легко зробити, коли виконується тіло циклу. Однак у випадку, коли тіло оператора FOR слід пропустити, як це дозволяє BASIC-80, як BASIC знайшов операцію NEXT, враховуючи, що це може бути перед оператором FOR у порядку джерела?

  • Чи завжди версія BASIC, що використовується в "101 Основних комп'ютерних іграх", виконувала тіло циклу хоча б один раз?
  • Чи вимагав BASIC-80, щоб після оператора FOR виникло наступне твердження циклу FOR, у порядку джерела?

PS: Так, я пишу перекладача BASIC для старої школи BASIC. Це хвороба.


Книга Ahl була спочатку опублікована DEC в 1973 році, передуючи Microsoft BASIC на два роки. Програми, ймовірно, були б виконані в RT-11 BASIC або BASIC-PLUS. Окрім розширень, що стосуються конкретної системи, більшість діалектів були сумісні, і я керував програмами з версії книги DEC на декількох системах з невеликими або без труднощів. Ви можете виявити розібрані, задокументовані джерела просвітницького програмного забезпечення Applesoft BASIC. Код, який реалізує NEXTоператор, починається з $ DCF9.
Blrfl

Не знаю про BASIC-80, але я на 100% впевнений, що Commodore Basic (який був Microsoft BASIC V2) завжди виконує цикл один раз, і порядок висловлювань у джерелі не має значення - так само, як ви підозрюєте.
Док Браун

Відповіді:


7

Це повертає колишні часи ...

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

200 LETK=M:GOSUB600

Діалект - це DIGITAL PDP-11 BASIC (не Basic-plus або BASIC-80). З досвіду, не всі ці ігри працювали на всіх діалектах BASIC. У мене є невиразний спогад про необхідність перечитати кілька цих ігор, щоб змусити їх працювати над іншими діалектами. Така жахлива структура петлі, безумовно, була проблемою.

Я мав досвід роботи з більш ніж 20 різними діалектами BASIC, і можу вам сказати, що це було напевне питання на той час. Було 2 основних табори.

В одному таборі були повні перекладачі, які щоразу, коли їх бачили, знову аналізували кожен рядок. Вони обробляли цикл FOR, натискаючи на стек, ідентифікований за його змінною, а потім скануючи стек на відповідність кожному NEXT. Якщо вони пропустили цикл, вони повинні були б сканувати джерело для наступного. Деякі робили, інші ні.

Інший табір - токенізатори або напівкомпілятори. Вони будуть сканувати всі рядки перед виконанням та конвертувати їх у якийсь внутрішній формат. Вони також підходили до циклів FOR / NEXT та перевіряли відсутність цілей GOTO та GOSUB. Як я пам’ятаю, DEC та BASIC-80 були в цьому таборі, але це було давно.

Відповідаючи на ваші запитання,

  1. Так, діалект BASIC пропускає цикл, якщо спочатку це задоволено
  2. Ні, послідовність ДЛЯ НАДНІХ не була документально підтвердженою вимогою, але поведінка була не визначеною. Як професіонал явно ніколи цього не робив. :)

Сподіваюсь, це допомагає. Це жахливі мови, але якщо ти повинен це зробити ...


Це дуже корисно, дякую. У книзі є версія 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 не виконає NEXT у циклі 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 НАСТУПНУЄ верхню петлю ДЛЯ, а не нижню.

Це очевидно в повідомленні про помилку "НАЙКЛЮЧЕНО без"; інтерпретатор BASIC відхиляє будь-яку НАСТУПНУ, для якої не знайшов відповідного ЗА. Зазвичай це відбувається, коли ваш NEXT вийшов з ладу, як в

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".
Док Браун

Специфікація існує. Пошук PDP-11 BASIC.
david.pfx

1
Дякую за те, що вдарили по цьому дивному питанню. Тепер я підтвердив, що BASIC, що використовується в книзі, коли зустрічає другий оператор FOR, що має ту саму змінну лічильника, забуває про перший оператор FOR і перезапускає цикл з другого. Це суперечить вашому удару в темряві. Це одіозний спосіб написання циклів, але BASIC все одно смердючий матеріал.
Уейн Конрад

2

Що робить BASIC "101 комп'ютерні ігри"

Діалект BASIC, використаний у виданні мікрокомп'ютерів "101 Комп'ютерних ігор", виконає тіло ЗА ... НАЙКЛЮЧЕНОГО циклу хоча б один раз. Це дійсно відрізняється від BASIC-80 v. 5 .

З с. i12 , перераховуючи винятки з "нормальної" ОСНОВИ :

ДЛЯ ... ДО ... КРОК

Як і у стандартній BASIC, за винятком того, що тест на закінчення циклу проводиться після того, як він буде виконаний. Тобто, коли ця програма запускається:

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

"HI" буде надруковано ...

Через те, цей діалект BASIC не має проблем з розміщенням оператора NEXT або спільним використанням наступного твердження з кількома операторами FOR. Не потрібно статичного аналізу. Просто виконайте кожне твердження у міру його виникнення, і ви, зрештою, перейдете до наступного оператора, де б він не був.

Чи можливо для BASIC-80 обробляти НАСТУПНІ ЗАПОВЕДЕННЯ?

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

  • Перекладач отримує два стани: "біг" і "перехід до НАСТУПНОГО"
  • Перебуваючи в стані "запущеного", інтерпретатор виконує кожне твердження нормально.
  • Оцінюючи оператор FOR, якщо тіло циклу потрібно пропустити, стан змінюється на "пропуск до наступного"
  • Перебуваючи в стані "перехід до наступного", перекладач пропускає кожне твердження, за винятком НАСТУПНОГО та безумовного GOTO.
    • Дотримується безумовного твердження GOTO
    • Наступний оператор NEXT, якщо його змінна збігається з твердженням FOR (або якщо змінна не вказана), повертається до стану "запущеного". Якщо змінна не збігається, інтерпретатор залишається у стані "перехід до НАСТУПНОГО".

Це вирішило б прості патологічні послідовності, такі, як у питанні. Він би не обробляв випадки, коли НАЙКЛЮЧЕНО було досягнуто операцією IF ... GOTO або GOSUB. Код, який це робить, є набагато гіршим, ніж і без того поганий код у питанні, що нерозумно просто заявити, що перекладач не підтримуватиме такі випадки. Перекладачу може бути навіть дозволено підпалювати такий код.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.