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.
la source
NEXT
instruction commence à $ DCF9.Réponses:
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
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,
J'espère que cela t'aides. Ce sont des langues horribles, mais si tu dois le faire ...
la source
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
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
Donc, pour répondre à vos questions à puces:
la source
À 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
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:
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.
la source