GOTO (etc) vers une ligne inexistante?
L'écriture d' un interpréteur BASIC a révélé un certain nombre d'informations intéressantes qui ont tendance à ne pas être mentionnées dans la documentation. Par exemple:
10 PRINT"ONE";:IF 1=2 THEN PRINT"TWO":PRINT"THREE"
Imprimera ONE
sur les BASIC dérivés de Microsoft, tandis que Dartmouth produira ONETHREE
. Autrement dit, MS traite tout le reste de la ligne comme faisant partie du THEN
, ce qui est ... bizarre (et faux à mon humble avis). Je n'ai remarqué cela que parce que l'exemple de code que j'avais a exécuté la dernière instruction, ce qui a provoqué l'échec de Super Star Trek.
Je suis tombé sur un autre exemple que j'aimerais ouvrir au hoi polloi. Considérez ce programme:
10 PRINT"HELLO"
20 GOTO 25
30 PRINT"WORLD"
L'exemple de code que j'ai chercherait à la ligne 25 ou à l'instruction supérieure suivante . Donc, dans ce code, la ligne 30 serait exécutée. Ce n'est certainement pas le cas pour Commodore BASIC, qui renvoie "UNDEFN'D STATEMENT".
Alors ... est-ce que quelqu'un connaît une version de BASIC qui fonctionne de cette façon, ou est-ce (comme je le soupçonne fortement) simplement un bogue dans l'exemple de code?
Réponses
Sinclair BASIC sur le ZX Spectrum passerait au prochain numéro de ligne disponible. Le manuel dit
Si le numéro de ligne dans une commande GO TO fait référence à une ligne inexistante, alors le saut est à la ligne suivante après le numéro donné. Il en va de même pour RUN; en fait, RUN seul signifie en fait RUN 0.
Les dialectes de BASE sont connus pour varier considérablement dans les détails. L'une des versions les plus définitives est BBC BASIC, qui effectue les opérations suivantes:

Notez la construction IF-THEN-ELSE, qui justifie l'utilisation de corps IF-THEN multi-instructions - qui sont en fait utiles en pratique.
BBC BASIC V a ajouté un mot-clé ENDIF et la possibilité de blocs IF-THEN-ELSE-ENDIF multilignes. En général, BBC BASIC est conçu pour rendre la programmation structurée plus facile que la plupart des BASIC de micro-ordinateur antérieurs.
Les exemples ne sont pas des bogues mais un comportement indéfini, ce qui est également courant dans d'autres langages. Si vous vous attendez à une compatibilité multiplateforme, ne faites tout simplement pas les choses qui entraînent un comportement indéfini.
De plus, l'intention du programmeur dans le premier exemple n'est pas claire, ce qui peut conduire à des bogues difficiles à corriger. Encore une fois, ne faites pas ça. Le deuxième exemple est meilleur car soit il fonctionne comme le programmeur l'a prévu, soit l'analyseur se plaint, ce qui facilite la recherche et la correction rapide du bogue.
10 PRINT"ONE";:IF 1=2 THEN PRINT"TWO":PRINT"THREE"
Imprime ONE sur les BASIC dérivés de Microsoft, tandis que Dartmouth en produira ONETHREE. Autrement dit, MS traite tout le reste de la ligne dans le cadre du THEN, ce qui est ... bizarre (et faux à mon humble avis).
Eh bien, je suppose qu'il n'y a pas de bien ou de mal, mais la manière de chaque BASIC. MS 'permet essentiellement la création d'un bloc de code dans une clause THEN sans avoir besoin de GOTO. Avec Dartmouth, qui fonctionne à ce stade comme FORTRAN auparavant, le THEN doit sauter dans le bloc de code, suivi d'un GOTO pour se déplacer:
10 PRINT"ONE";
20 IF 1=2 THEN GOTO 40
30 GOTO 50
40 PRINT"TWO"
50 PRINT"THREE"
60 REM
Eh bien, ou utilisez une clause inversée pour contourner le bloc de code. Ni une très bonne construction.
Il faut noter qu'autoriser les déclarations arbitraires après THEN est un module complémentaire ultérieur, non présent dans Dartmouth BASIC. Il en va de même avec plusieurs instructions séparées par deux-points.
Avec la manière de MS de traiter l'ensemble (reste de la) ligne dans le cadre du bloc then, cela permet de construire sans beaucoup de jogging cérébral et de gotos.
Mais il n'a pas été inventé par MS, ils l'ont juste pris de DEC BASIC-PLUS de 1972 (après tout, MS BASIC est un clone de DEC BASIC) comme décrit aux p.3-12 du manuel:

Donc, après un THEN, plusieurs instructions sont autorisées, mais exécutées dans leur intégralité (si la condition est vraie) ou pas du tout.
Maintenant, lorsque vous recherchez les «bonnes» méthodes, il est généralement préférable de commencer par jeter un œil aux normes BASIC. Le premier ici pourrait être
ECMA 55 Minimal BASIC de 1978
Ceci décrit le minimum que chaque BASIC doit respecter pour être portable. Essentiellement, il codifie Dartmouth BASIC (Thomas Kurtz était l'un des éditeurs) dans ses incarnations ultérieures d'une manière claire et reproductible. Ici, les instructions THEN autorisent uniquement le saut d'un numéro de ligne.
ANSI Minimal BASIC de 1979
Essentiellement la version ANSI de l'ECMA-55.
C'est BTW, le moment où MS-BASIC a commencé à devenir une force normative
ECMA 116 BASIC de 1986 , également appelé 'Full BASIC'
Ici, les constructions multi-instructions et multi-lignes ALORS et leurs mélanges sont possibles. L'instruction multi fonctionne comme la «manière MS», tandis que la multi-ligne a besoin d'une instruction ENDIF (ou ELSE / ELSEIF) pour fermer le bloc. (Il a également de nombreuses autres fonctionnalités nie connues des BASIC modernes, juste avec les numéros de ligne)
ANSI / ISO / IEC Full BASIC de 1987
Essentiellement ECMA-116 avec quelques clarifications / extensions.
Donc, MS suit ce que dit l'ECMA-116 ... eh bien, ou mieux, peut-être que la norme codifie ce que MS a fait auparavant et est donc devenue une norme de facto. Beaucoup de travail a été mis dans ces normes pour capturer une place commune viable pour BASIC. Cela inclut en particulier les cas extrêmes de problèmes apparemment clairs. Je considère qu'il est préférable de les vérifier chaque fois qu'il y a quelque chose à discuter. Surtout parce qu'ils soulignent également des questions qui n'ont pas été décidées / sont encore sujettes à interprétation.
L'exemple de code que j'ai rechercherait à la ligne 25 ou à l'instruction suivante [...]
Alors ... est-ce que quelqu'un connaît une version de BASIC qui fonctionne de cette façon, ou est-ce (comme je le soupçonne fortement) simplement un bogue dans l'exemple de code?
Je me souviens d'un TINY BASIC qui permettait de sauter «entre» les lignes pour faciliter le calcul de GOTO, mais en regardant la source originale, il semble que c'était une modification.
En revanche, l'ECMA-55 indique sur les cibles utilisées comme cibles dans THEN / GOTO / GOSUB:
All line-numbers in control-statements shall refer to lines in the program.
En termes pragmatiques,
Décidez du code hérité que vous voulez que votre interpréteur puisse exécuter
Décidez quels dialectes incompatibles, le cas échéant, vous souhaitez prendre en charge comme options
Faites la même chose qu'eux.
Comme Raffzahn le souligne, le comportement de Microsoft est plus pratique que celui de Dartmouth, car Microsoft BASIC vous permet d'écrire un bloc conditionnel avec plusieurs instructions. Vous dites également que vous souhaitez exécuter des programmes qui s'attendent au comportement de Microsoft.
De même, il est très peu probable qu'un code hérité contienne intentionnellement GOTO
une ligne qui n'existe pas, mais il est possible qu'un programme existant s'exécute correctement malgré une faute de frappe comme GOTO 24
au lieu de GOTO 25
.
Si vous avez également besoin d'exécuter du code qui dépend d'un comportement incompatible, vous pouvez le fournir en option.
Le dialecte que j'ai utilisé passait le contrôle à la ligne existante avec le plus grand nombre le plus proche, si tel était le cas. Sinon, c'était le moyen légitime de terminer le programme sans aucun message d'erreur.
Passer le contrôle au milieu de la plage permettait d'ajouter des lignes de chaque côté du point d'entrée. Cela a beaucoup aidé car le refactoring était également très fastidieux: il n'y avait pas de recherche et la seule façon de changer la ligne était de la retaper dans son intégralité. Cette version ne comportait pas de numérotation automatique de ligne.
La machine était une sorte de "Elektronika" soviétique mais je ne me souviens pas précisément. Cela ressemblait plus à une calculatrice très haut de gamme avec son propre écran LED à deux rangées sur la console, mais déjà pris en charge par un moniteur et un clavier externes.