Comment BASIC trouve-t-il une instruction NEXT hors service lorsque le corps de la boucle est ignoré

9

Réglez la machine WABAC , Sherman. Cette question concerne BASIC en général, et BASIC-80 de Microsoft en particulier. Old school basique. Avec des numéros de ligne.

Comment (ou, plutôt, les interprètes BASIC old-school ont-ils géré les boucles FOR ... NEXT lorsque le corps de la boucle n'a pas été exécuté et que l'instruction NEXT est apparue dans le désordre?

Une instruction NEXT désordonnée de l'heure précédente:

Voici un sous-programme du jeu Awari de "101 Basic Computer Games" de David H. Ahl :

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

et le voici avec tout sauf le contrôle de flux expurgé:

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

Cela ramène-t-il des souvenirs moins sympathiques? Peux-tu entendre Dijkstra se retourner dans sa tombe?

Voici la partie intéressante de ce qui se passe dans ce fragment:

  • La deuxième boucle FOR, car elle utilise la même variable de boucle, remplace la première boucle FOR
  • Les deux boucles FOR partagent la même instruction NEXT
  • La deuxième instruction NEXT de la boucle FOR vient avant elle, dans l'ordre source, mais après elle, dans l'ordre d'exécution

Vous pourriez alors supposer que l'interpréteur, ayant démarré une boucle FOR, exécute simplement des instructions jusqu'à ce qu'il se produise dans la boucle NEXT. L'ordre de la déclaration dans la source n'a pas d'importance dans ce cas. Mais voyons ce que le manuel de base80 a à dire sur les boucles FOR:

Le manuel de base-80 dit "moo ..."

Le corps de la boucle est ignoré si la valeur initiale de la boucle multipliée par le signe de l'étape dépasse la valeur finale multipliée par le signe de l'étape.

Ainsi, le corps de la boucle peut être entièrement ignoré.

Nous avons des preuves, sous forme de programmes publiés, qu'au moins certaines versions de BASIC localisaient dynamiquement leurs instructions NEXT. C'est assez facile à faire lorsque le corps de la boucle est en cours d'exécution. Cependant, dans le cas où le corps de l'instruction FOR devrait être ignoré, comme le permet BASIC-80, comment BASIC a-t-il localisé l'instruction NEXT, étant donné qu'elle pourrait se trouver avant l'instruction FOR dans l'ordre source?

  • La version de BASIC utilisée dans "101 Basic Computer Games" a-t-elle toujours exécuté le corps de la boucle au moins une fois?
  • BASIC-80 a-t-il exigé que l'instruction NEXT d'une boucle FOR se produise après l'instruction FOR, dans l'ordre source?

PS: Oui, j'écris un interprète BASIC pour la vieille école BASIC. C'est une maladie.

Wayne Conrad
la source
Le livre Ahl a été initialement publié par DEC en 1973, précédant Microsoft BASIC de deux ans. Les programmes auraient probablement été réalisés en RT-11 BASIC ou BASIC-PLUS. Outre les extensions spécifiques au système, la plupart des dialectes étaient compatibles, et j'ai exécuté des programmes de la version DEC du livre sur plusieurs systèmes avec peu ou pas de difficulté. Vous pourriez trouver les sources documentées et démontées de la ROM Applesoft BASIC éclairante. Le code qui implémente l' NEXTinstruction commence à $ DCF9.
Blrfl
Je ne sais pas pour BASIC-80, mais je suis sûr à 100% que Commodore Basic (qui était Microsoft BASIC V2) exécute toujours la boucle une fois, et l'ordre des instructions dans la source n'a pas d'importance - tout comme vous le suspectez.
Doc Brown

Réponses:

7

Cela ramène les temps anciens ...

J'ai une copie du livre, 3e impression, 1975. J'ai vérifié votre liste et elle n'est pas originale. Dans le code source d'origine, les instructions n'ont pas d'espaces et les affectations ont le mot clé LET. Par exemple

200 LETK=M:GOSUB600

Le dialecte est DIGITAL PDP-11 BASIC (pas Basic-plus ou BASIC-80). Par expérience, tous ces jeux n'ont pas fonctionné sur tous les dialectes de BASIC. J'ai un vague souvenir d'avoir à recoder plusieurs de ces jeux pour les faire travailler sur d'autres dialectes. Ce genre de structure de boucle horrible était définitivement un problème.

J'avais de l'expérience avec plus de 20 dialectes différents de BASIC et je peux vous dire que c'était une question épineuse à l'époque. Il y avait 2 camps principaux.

Dans un camp, il y avait des interprètes complets, qui analysaient chaque ligne à nouveau chaque fois qu'elle était vue. Ils ont géré une boucle FOR en la poussant sur une pile, identifiée par sa variable, puis en balayant la pile pour une correspondance avec chaque NEXT. S'ils sautaient une boucle, ils devraient balayer la source pour le NEXT. Certains l'ont fait, d'autres non.

L'autre camp était les tokenizers ou semi-compilateurs. Ils analysaient toutes les lignes avant l'exécution et les convertissaient en une sorte de format interne. Ils ont également fait correspondre les boucles FOR / NEXT et vérifié les cibles GOTO et GOSUB manquantes. DEC et BASIC-80 étaient dans ce camp, si je me souviens bien, mais il y a longtemps.

En réponse à vos questions,

  1. Oui, le dialecte de BASIC saute une boucle s'il est initialement satisfait
  2. Non, le séquençage de FOR NEXT n'était pas une exigence documentée, mais le comportement n'était pas défini. En tant que professionnel, je ne l'ai évidemment jamais fait. :)

J'espère que cela t'aides. Ce sont des langues horribles, mais si tu dois le faire ...

david.pfx
la source
C'est très utile, merci. Le livre a une version DEC, une version TRS-80 et une version micro-ordinateur. Les programmes de la version micro-ordinateur sont en Microsoft 8080 basic (MITS Altair Basic Rev 4.0); c'est la cible de mon interprète.
Wayne Conrad
J'ai utilisé MBASIC sur CP / M vers 1980, mais aucune de ces machines d'amateur antérieures. Vous avez besoin d'un système de fichiers! À bien des égards, je trouverais une réincarnation d'un DEC / DG / HP / CAI / Prime / Interdata / Tektronix Basic plus intéressante, mais je peux comprendre pourquoi vous ne pourriez pas. Bonne chance! Contactez-moi si je peux vous aider.
david.pfx
2

Je n'ai pas de copie de la spécification pour l'un de ces anciens interprètes BASIC devant moi (cela peut même ne pas exister), mais je vais sortir sur une branche et dire que l'interprète BASIC n'exécutera pas de SUIVANT sur une boucle FOR qui ne lui appartient pas, même si la variable de boucle porte le même nom.

Donc, en d'autres termes, dans votre exemple

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

lorsque la ligne 235 s'exécute et passe à la ligne 220, la ligne 220 NEXT la boucle FOR supérieure, pas la boucle inférieure.

Cela est évident dans le message d'erreur "NEXT without FOR"; l'interpréteur BASIC rejette tout NEXT pour lequel il n'a pas trouvé de FOR correspondant. Cela se produit généralement lorsque vous mettez vos NEXT hors service, comme dans

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

Donc, pour répondre à vos questions à puces:

  • Oui, si la variable de boucle est dans la plage du FOR.
  • Oui, à ma connaissance, c'est le cas.
Robert Harvey
la source
2
"l'interpréteur BASIC n'exécutera pas un NEXT sur une boucle FOR qui ne lui appartient pas" - Je connais au moins une famille d'anciens interprètes BASIC où cette déclaration est erronée, vous ne pouvez pas généraliser cela à "tous les anciens interprètes BASIC".
Doc Brown
La spécification existe. Recherchez PDP-11 BASIC.
david.pfx
1
Merci d'avoir essayé cette étrange question. J'ai maintenant confirmé que le BASIC utilisé dans le livre, lorsqu'il rencontre la deuxième instruction FOR ayant la même variable de compteur, oublie la première instruction FOR et redémarre la boucle à partir de la seconde. Cela contredit votre coup de couteau dans le noir. C'est une façon odieuse d'écrire des boucles, mais BASIC est quand même malodorant.
Wayne Conrad
2

À quoi sert le BASIC "101 Computer Games"

Le dialecte de BASIC utilisé dans l'édition Micro-ordinateur de "101 Computer Games" exécutera le corps d'une boucle FOR ... NEXT au moins une fois. Cela diffère de BASIC-80 v. 5 .

De la p. i12 , énumérant les exceptions à BASIC "normal":

POUR ... À ... ÉTAPE

Comme dans BASIC standard, sauf que le test pour terminer la boucle est effectué après qu'il a été exécuté. Autrement dit, lorsque ce programme est exécuté:

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

"HI" sera imprimé ...

Pour cette raison, ce dialecte de BASIC n'a aucun problème à localiser l'instruction NEXT ou à partager la même instruction suivante avec plusieurs instructions FOR. Aucune analyse statique n'est requise. Exécutez simplement chaque instruction au fur et à mesure qu'elle se produit et vous finirez par accéder à l'instruction NEXT, où qu'elle se trouve.

Est-il possible pour BASIC-80 de gérer un NEXT hors service?

Il est possible qu'une instruction FOR ignore le corps de la boucle, comme le permet BASIC-80 v.5, et autorise toujours les instructions NEXT dans le désordre dans la plupart des cas. Voici comment:

  • L'interprète obtient deux états, "en cours d'exécution" et "passer à NEXT"
  • Lorsqu'il est à l'état "en cours d'exécution", l'interpréteur exécute normalement chaque instruction.
  • Lors de l'évaluation d'une instruction FOR, si le corps de la boucle doit être ignoré, l'état est remplacé par "ignorer NEXT"
  • Lorsqu'il est dans l'état "passer à la prochaine", l'interpréteur ignore toutes les instructions sauf NEXT et GOTO inconditionnel.
    • Une instruction GOTO inconditionnelle est suivie
    • Une instruction NEXT, si sa variable correspond à celle de l'instruction FOR (ou si la variable n'est pas spécifiée), repasse à l'état "en cours d'exécution". Si la variable ne correspond pas, l'interpréteur reste dans l'état "sauter à NEXT".

Cela traiterait des séquences pathologiques simples comme celle de la question. Il ne traiterait pas les cas où le NEXT a été atteint par une instruction IF ... GOTO ou un GOSUB. Le code qui fait cela est tellement pire que le code déjà mauvais dans la question qu'il n'est pas déraisonnable de simplement déclarer que l'interprète ne prendra pas en charge de tels cas. Il pourrait même être permis à l'interprète de mettre le feu à un tel code.

Wayne Conrad
la source