W jaki sposób BASIC lokalizuje instrukcję NEXT poza kolejnością, gdy ciało pętli jest pomijane

9

Ustaw maszynę WABAC , Sherman. To pytanie dotyczy ogólnie BASIC, a szczególnie BASIC-80 Microsoftu . Podstawowa stara szkoła. Z numerami linii.

Jak (a raczej) staroszkolni tłumacze BASIC radzą sobie z pętlami FOR ... NEXT, gdy ciało pętli nie zostało wykonane, a instrukcja NEXT pojawiła się w kolejności?

Komunikat NEXT o braku zamówienia z wcześniejszego okresu:

Oto podprogram z gry Awari z „101 podstawowych gier komputerowych” Davida H. Ahla :

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

i tutaj jest wszystko z wyjątkiem zredagowanej kontroli przepływu:

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

Czy to przywraca niezbyt miłe wspomnienia? Czy słyszysz, jak Dijkstra przewraca się w grobie?

Oto interesująca część tego, co dzieje się w tym fragmencie:

  • Druga pętla FOR, ponieważ wykorzystuje tę samą zmienną pętli, zastępuje pierwszą pętlę FOR
  • Dwie pętle FOR mają tę samą instrukcję NEXT
  • Druga instrukcja NEXT w pętli FOR występuje przed nią w kolejności źródłowej, ale po niej w kolejności wykonania

Można zatem przypuszczać, że interpreter, po uruchomieniu pętli FOR, po prostu uruchamia instrukcje, aż stanie się to w pętli NEXT. W tym przypadku kolejność instrukcji w źródle nie ma znaczenia. Zobaczmy jednak, co ma do powiedzenia instrukcja obsługi basic80 na temat pętli FOR:

Podręcznik Basic-80 mówi „moo ...”

Treść pętli jest pomijana, jeśli początkowa wartość pętli razy znak kroku przekracza końcową wartość razy znak kroku.

Tak więc korpus pętli można całkowicie pominąć.

Mamy dowody w postaci opublikowanych programów, że przynajmniej niektóre wersje BASIC dynamicznie lokalizują swoje NASTĘPNE instrukcje. Jest to dość łatwe do wykonania, gdy wykonywane jest ciało pętli. Jednak w przypadku, gdy treść instrukcji FOR powinna zostać pominięta, jak pozwala BASIC-80, w jaki sposób BASIC zlokalizował instrukcję NEXT, biorąc pod uwagę, że może ona znajdować się przed instrukcją FOR w kolejności źródłowej?

  • Czy wersja BASIC zastosowana w „101 podstawowych grach komputerowych” zawsze wykonywała ciało pętli przynajmniej raz?
  • Czy BASIC-80 wymagał, aby instrukcja NEXT pętli FOR występowała po instrukcji FOR w kolejności źródłowej?

PS: Tak, piszę tłumacza w języku BASIC dla starej szkoły języka BASIC. To jest choroba

Wayne Conrad
źródło
Książka Ahl została pierwotnie wydana przez DEC w 1973 roku, wyprzedzając Microsoft BASIC o dwa lata. Programy prawdopodobnie zostałyby wykonane w RT-11 BASIC lub BASIC-PLUS. Poza rozszerzeniami specyficznymi dla systemu większość dialektów była kompatybilna, a na kilku systemach uruchomiłem programy z wersji DEC książki na kilku systemach, z niewielką lub żadną trudnością. Możesz znaleźć zdemontowane, udokumentowane źródła oświecającego Applesoft BASIC ROM. Kod implementujący NEXTinstrukcję zaczyna się od $ DCF9.
Blrfl
Nie wiem o BASIC-80, ale jestem 100% pewien, że Commodore Basic (którym był Microsoft BASIC V2) zawsze wykonuje pętlę raz, a kolejność instrukcji w źródle nie ma znaczenia - tak jak podejrzewasz.
Doc Brown

Odpowiedzi:

7

To przywraca dawne czasy ...

Mam kopię książki, 3 wydanie, 1975 r. Sprawdziłem twój wpis i nie jest on oryginalny. W oryginalnym kodzie źródłowym instrukcje nie mają spacji, a przypisania mają słowo kluczowe LET. Na przykład

200 LETK=M:GOSUB600

Dialekt to DIGITAL PDP-11 BASIC (nie Basic-plus ani BASIC-80). Z doświadczenia wynika, że ​​nie wszystkie z tych gier działały na wszystkich dialektach języka BASIC. Mam niejasne wspomnienie o konieczności przekodowania kilku z tych gier, aby mogły one działać na innych dialektach. Ten rodzaj okropnej struktury pętli był zdecydowanie problemem.

Miałem doświadczenie z ponad 20 różnymi dialektami języka BASIC i mogę powiedzieć, że było to wtedy dokuczliwe pytanie. Były 2 główne obozy.

W jednym obozie byli tłumacze, którzy za każdym razem analizowali każdą linię od nowa. Obsługiwali pętlę FOR, pchając ją na stos, identyfikowany przez jej zmienną, a następnie skanując stos pod kątem dopasowania z każdym NASTĘPNYM. Gdyby pominęli pętlę, musieliby przeskanować źródło w poszukiwaniu DALEJ. Niektórzy tak, inni nie.

Drugi obóz to tokenizery lub półkompilatory. Skanują wszystkie wiersze przed wykonaniem i konwertują je na jakiś format wewnętrzny. Dopasowali także pętle FOR / NEXT i sprawdzili, czy brakuje celów GOTO i GOSUB. DEC i BASIC-80 były, jak pamiętam, w tym obozie, ale to już dawno.

W odpowiedzi na twoje pytania

  1. Tak, dialekt języka BASIC pomija pętlę, jeśli początkowo jest spełniony
  2. Nie, sekwencjonowanie FOR NEXT nie było udokumentowanym wymaganiem, ale zachowanie było niezdefiniowane. Jako profesjonalista oczywiście nigdy tego nie zrobiłem. :)

Mam nadzieję że to pomoże. To okropne języki, ale jeśli musisz to zrobić ...

david.pfx
źródło
To bardzo pomocne, dziękuję. Książka ma wersję DEC, wersję TRS-80 i wersję mikrokomputerową. Programy w wersji mikrokomputerowej są w systemie Microsoft 8080 basic (MITS Altair Basic Rev 4.0); to jest cel mojego tłumacza.
Wayne Conrad
Użyłem MBASIC na CP / M około 1980 roku, ale żadnej z tych wcześniejszych maszyn hobbystycznych. Potrzebujesz systemu plików! Na wiele sposobów uważam reinkarnację DEC / DG / HP / CAI / Prime / Interdata / Tektronix Basic za bardziej interesującą, ale rozumiem, dlaczego nie. Powodzenia! Skontaktuj się ze mną, jeśli mogę pomóc.
david.pfx
2

Nie mam przed sobą kopii specyfikacji jednego z tych starożytnych tłumaczy BASIC (może nawet nie istnieć), ale zamierzam wyjść na zewnątrz i powiedzieć, że tłumacz BASIC nie wykona polecenia DALEJ w pętli FOR, która do niej nie należy, nawet jeśli zmienna pętli ma tę samą nazwę.

Innymi słowy, w twoim przykładzie

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

gdy linia 235 zostanie wykonana i przejdzie do linii 220, linia 220 NASTĘPUJE górną pętlę FOR, a nie dolną.

Jest to widoczne w komunikacie o błędzie „NASTĘPNY bez FOR”; interpreter języka BASIC odrzuca każdy NASTĘPNY, dla którego nie znalazł odpowiedniego FOR. Zwykle dzieje się tak, gdy Twoje NEXT są w porządku, jak w

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

Aby odpowiedzieć na wypunktowane pytania:

  • Tak, jeśli zmienna pętli mieści się w zakresie FOR.
  • Tak, o ile mi wiadomo, tak właśnie jest.
Robert Harvey
źródło
2
„Tłumacz BASIC nie wykona NASTĘPNEJ w pętli FOR, która do niego nie należy” - znam przynajmniej jedną rodzinę starych tłumaczy BASIC, w których to stwierdzenie jest błędne, nie można uogólniać tego na „wszystkich starożytnych tłumaczy BASIC”.
Doc Brown
Specyfikacja istnieje. Wyszukaj PDP-11 BASIC.
david.pfx
1
Dziękuję za ugodzenie tego dziwnego pytania. Potwierdziłem teraz, że język BASIC użyty w książce, gdy napotyka drugą instrukcję FOR mającą tę samą zmienną licznika, zapomina o pierwszej instrukcji FOR i restartuje pętlę od drugiej. To zaprzecza twojemu dźgnięciu w ciemność. To wstrętny sposób na pisanie pętli, ale BASIC i tak jest śmierdzący.
Wayne Conrad
2

Czym zajmuje się BASIC „101 gier komputerowych”

Dialekt języka BASIC zastosowany w wydaniu „101 gier komputerowych” mikrokomputera przynajmniej raz wykona ciało pętli FOR ... NEXT. Różni się to od BASIC-80 v.5 .

Od p. i12 , wymieniając wyjątki od „normalnego” języka BASIC:

DLA ... DO ... KROKU

Jak w standardowym języku BASIC, z tym wyjątkiem, że test zakończenia pętli jest wykonywany po jej wykonaniu. Oznacza to, że po uruchomieniu tego programu:

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

„HI” zostanie wydrukowane ...

Z tego powodu ten dialekt języka BASIC nie ma problemu ze zlokalizowaniem instrukcji NEXT lub współdzieleniem tej samej kolejnej instrukcji z wieloma instrukcjami FOR. Nie jest wymagana analiza statyczna. Po prostu wykonaj każdą instrukcję, jaka się pojawi, a w końcu przejdziesz do instrukcji NEXT, gdziekolwiek się ona znajduje.

Czy BASIC-80 jest w stanie obsłużyć NEXT poza kolejnością?

Instrukcja FOR może pominąć ciało pętli, ponieważ BASIC-80 v.5 zezwala i nadal dopuszcza instrukcje NEXT poza kolejnością w większości przypadków. Oto jak:

  • Tłumacz otrzymuje dwa stany: „działa” i „przeskakuje do NASTĘPNEGO”
  • W stanie „uruchomionym” interpreter wykonuje każdą instrukcję normalnie.
  • Podczas oceny instrukcji FOR, jeśli ciało pętli ma zostać pominięte, stan zmienia się na „przejście do NASTĘPNE”
  • W stanie „przeskakiwania do następnego” interpreter pomija każdą instrukcję oprócz DALEJ i bezwarunkowego GOTO.
    • Następuje bezwarunkowa instrukcja GOTO
    • Instrukcja NEXT, jeśli jej zmienna jest zgodna ze zmienną instrukcji FOR (lub jeśli zmienna nie jest określona), przełącza się z powrotem do stanu „uruchomionego”. Jeśli zmienna nie pasuje, interpreter pozostaje w stanie „przechodzenia do NASTĘPNEGO”.

To poradziłoby sobie z prostymi sekwencjami patologicznymi, takimi jak w pytaniu. Nie obsługuje przypadków, w których NEXT został osiągnięty przez instrukcję IF ... GOTO lub GOSUB. Kod, który to robi, jest o wiele gorszy niż już zły kod w pytaniu, że nie jest nierozsądne oświadczenie, że tłumacz nie będzie obsługiwał takich przypadków. Tłumacz może nawet podpalić taki kod.

Wayne Conrad
źródło