INTERCAL (C-INTERCAL), 15 codes, 313 + 2 = 315 octets
PLEASE WRITE IN .1
(8) PLEASE CREATE .1 A
PLEASE A
PLEASE COME FROM #2$!1/#1'
DO X
(123) DO (123) NEXT
DO COME FROM (222)
(222) DO STASH .2
(240) DO ,1 <- #0
(241) DO ,1 SUB #0 <- #1
(19) DO .2 <- #256 $ #0
(21) DO .1 <- #2
(148) DO GO BACK
(180) DO RETRIEVE .2
DO COME FROM (50)
(50) DO WRITE IN .2
(109) DO RESUME #0
(120) DO RESUME #9
MAYBE COME FROM (223)
(223) DO COME FROM (223)
(121) PLEASE NOT X
Essayez-le en ligne!
Tous les espaces sont sans importance. (Le programme d'origine contenait des onglets, mais je les ai convertis en espaces pour qu'il s'aligne correctement sur SE. Il est classique d'utiliser une largeur de tabulation de 8 pour INTERCAL. J'ai testé une version du programme avec tous les onglets, espaces et les nouvelles lignes supprimées, cependant, et cela fonctionne bien.)
Compiler avec -abm
(pénalité de 2 octets, car il -b
est nécessaire pour que le compilateur soit déterministe).
Comme d'habitude pour INTERCAL, ceci prend une entrée numérique dans le format, par exemple, ONE TWO THREE
pour 123
.
Explication
En cas d'erreur de sortie d'un programme C-INTERCAL, l'état de sortie est le code d'erreur modulo 256. Par conséquent, nous pouvons essayer d'écrire un programme capable de générer autant d'erreurs d'exécution que possible. Ce programme n'omet que deux erreurs d'exécution qui n'indiquent pas d'incident interne du compilateur: ICL200I, car sa reproduction nécessite l'utilisation de bibliothèques externes compatibles uniquement avec un programme à un seul thread (et les programmes multithreads ayant davantage d'erreurs disponibles); et ICL533I, car 533 a la même valeur modulo 256 que 277, et le programme est capable de produire ICL277I.
Le programme commence toujours de la même manière. Tout d'abord, nous entrons ( WRITE IN
) une valeur pour la variable .1
. Ensuite, nous utilisons une CREATE
instruction calculée pour créer une nouvelle syntaxe (ici, A
); mais comme il est calculé, la définition de la syntaxe varie en fonction de la valeur de .1
. Enfin, dans la plupart des cas, nous exécutons notre nouvelle A
instruction, qui a été définie pour produire une erreur. Le tableau des définitions possibles que nous avons contient une définition pour chaque erreur d'exécution possible (autres que les exceptions énumérées ci-dessus).
Premièrement, il y a deux exceptions à ce régime général. (0)
n’est pas un numéro de ligne valide. Par conséquent, si l’utilisateur saisit ZERO
, nous passons de la deuxième ligne (numérotée (8)
) à la quatrième à l’aide d’une COME FROM
instruction calculée . Cela tombe ensuite dans une erreur de syntaxe DO X
, qui produit une erreur ICL000I
. (Dans INTERCAL, les erreurs de syntaxe se produisent lors de l'exécution, du fait que les commandes ont tendance à être désactivées, la syntaxe à être redéfinie sous vous, etc.). L' COME FROM
instruction a également un effet secondaire, même si rien ne COME FROM
se passe réellement , en créant une surcharge d'opérande de .1
à #1
chaque fois qu'une ligne avec un numéro de ligne est exécutée; ceci est utilisé plus tard lors de la production de la sortie 21. (Les effets secondaires globaux aléatoires sont assez idiomatiques dans INTERCAL.)
L'autre exception est avec entrée ONE TWO NINE
. Il n'y a pas de numéro de ligne (129)
dans le programme, nous obtenons donc une erreur pour un numéro de ligne manquant, qui est ICL129I
. Donc, je n'ai pas eu à écrire de code pour couvrir ce cas du tout.
Voici les autres erreurs et leurs causes:
- 123 est un
NEXT
débordement de pile ( DO (123) NEXT
). L' NEXT
instruction a besoin d'autres modificateurs ( FORGET
ou RESUME
) afin de déterminer de manière rétroactive de quel type d'instruction de contrôle il s'agissait. N'ayant pas ces causes, l'erreur ICL123I une fois qu'il existe 80 instructions `NEXT non résolues.
- 222 est un débordement de mémoire (
DO STASH .2
en COME FROM
boucle). Les caches ne sont limités que par la mémoire disponible, mais celle-ci finira par s'épuiser, provoquant l'erreur ICL222I.
- 240 est dimensions un tableau à la taille zéro. C’est exactement ce que cela
DO ,1 <- #0
signifie, et cela provoque l’erreur ICL240I.
- 241 est causée par l’affectation en dehors des limites d’un tableau. Dans ce cas,
,1
n'a pas été alloué ( ,
est utilisé pour les variables de type tableau dans INTERCAL), son indexation génère donc l'erreur ICL241I.
- 19 affecte 65536 (
#256 $ #0
) à une variable de 16 bits .2
. Cela ne convient pas, provoquant l'erreur ICL275I.
- 21 attribue
#2
à .1
. Cela peut sembler être une tâche assez simple, mais nous avons surchargé .1
le sens #1
précédent, et tenter de modifier la valeur de 1 sans -v
option sur la ligne de commande provoque l’erreur ICL277I.
- 148 tentatives pour revenir à l'entrée supérieure de la pile de choix (
GO BACK
), qui n'existe pas à ce stade du programme (nous n'avons exécuté aucune commande pour manipuler la pile de choix, elle est donc toujours vide). Cela provoque l'erreur ICL404I.
- 180 tentatives à
RETRIEVE .2
partir d'une réserve inexistante (car nous n'avons rien caché dans cette branche du programme), provoquant l'erreur ICL436I.
- 50 requêtes input (
WRITE IN
) pour toujours dans une COME FROM
boucle. Finalement, nous finirons par lire après EOF, provoquant l'erreur ICL562I.
- 109 exécute l'instruction
DO RESUME #0
, qui n'a pas de sens et est spécifiquement documentée comme provoquant une erreur (ICL621I).
- 120 exécute la déclaration
DO RESUME #9
. Nous n'avons pas encore exécuté beaucoup d' NEXT
énoncés et nous avons donc l'erreur ICL120I. (Curieusement, cette erreur particulière est définie dans la documentation INTERCAL comme quittant le programme normalement puis causant l'erreur, plutôt que de quitter le programme avec une erreur. Je ne crois cependant pas que ces deux cas soient différents.)
- 223 est fondamentalement un enchevêtrement complexe de primitives multithreading qui pointent toutes vers la ligne 223, provoquant une boucle infinie qui gonfle la mémoire. Éventuellement, le sous-système multithreading s’épuise en mémoire, ce qui entraîne l’erreur ICL991I.
- 121 est en fait une déclaration valide (c'est un commentaire), mais elle apparaît à la fin du programme. En tant que tel, l'exécution tombe à la fin du programme immédiatement après son exécution, ce qui provoque l'erreur ICL633I.
Vérification
Certaines des erreurs impliquent d'exécuter intentionnellement le programme avec peu de mémoire. Je suggère donc de définir des limites de mémoire assez petites. Voici la commande shell que j'ai utilisée pour tester le programme (avec de nouvelles lignes ajoutées pour la lisibilité; supprimez-les si vous l'exécutez vous-même):
for x in "ZERO" "ONE NINE" "TWO ONE" "FIVE ZERO" "ONE ZERO NINE"
"ONE TWO ZERO" "ONE TWO ONE" "ONE TWO THREE" "ONE TWO NINE"
"ONE FOUR EIGHT" "ONE EIGHT ZERO" "TWO TWO TWO"
"TWO TWO THREE" "TWO FOUR ZERO" "TWO FOUR ONE";
do echo;
echo $x;
echo $x | (ulimit -Sd 40000; ulimit -Sv 40000; ulimit -Ss 40000;
./errors; echo $?);
done
Et voici le résultat (avec les numéros de ligne et les messages "VEUILLEZ CORRIGER LA SOURCE" supprimés pour économiser de l'espace), que j'ai ajouté en partie pour montrer que le programme fonctionne, mais surtout pour afficher les messages d'erreur stupides d'INTERCAL:
ZERO
ICL000I PLEASEWRITEIN.1(8)PLEASECREATE.1APLEASEAPLEASECOMEFROM#2$!1/#1'DOX(123)DO(123)NEXTDOCOMEFROM(222)(222)DOSTASH.2(240)DO,1<-#0(241)DO,1SUB#0<-#1(19)DO.2<-#256$#0(21)DO.1<-#2(148)DOGOBACK(180)DORETRIEVE.2DOCOMEFROM(50)(50)DOWRITEIN.2(109)DORESUME#0(120)DORESUME#9MAYBECOMEFROM(223)(223)DOCOMEFROM(223)(121)PLEASENOTX
0
ONE NINE
ICL275I DON'T BYTE OFF MORE THAN YOU CAN CHEW
19
TWO ONE
ICL277I YOU CAN ONLY DISTORT THE LAWS OF MATHEMATICS SO FAR
21
FIVE ZERO
ICL562I I DO NOT COMPUTE
50
ONE ZERO NINE
ICL621I ERROR TYPE 621 ENCOUNTERED
109
ONE TWO ZERO
ICL632I THE NEXT STACK RUPTURES. ALL DIE. OH, THE EMBARRASSMENT!
120
ONE TWO ONE
ICL633I PROGRAM FELL OFF THE EDGE
121
ONE TWO THREE
ICL123I PROGRAM HAS DISAPPEARED INTO THE BLACK LAGOON
123
ONE TWO NINE
ICL129I PROGRAM HAS GOTTEN LOST
129
ONE FOUR EIGHT
ICL404I I'M ALL OUT OF CHOICES!
148
ONE EIGHT ZERO
ICL436I THROW STICK BEFORE RETRIEVING!
180
TWO TWO TWO
ICL222I BUMMER, DUDE!
222
TWO TWO THREE
ICL991I YOU HAVE TOO MUCH ROPE TO HANG YOURSELF
223
TWO FOUR ZERO
ICL240I ERROR HANDLER PRINTED SNIDE REMARK
240
TWO FOUR ONE
ICL241I VARIABLES MAY NOT BE STORED IN WEST HYPERSPACE
241