INTERCAL (C-INTERCAL), 15 códigos, 313 + 2 = 315 bytes
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
Pruébalo en línea!
Todo el espacio en blanco aquí es irrelevante. (El programa original contenía pestañas, pero las convertí en espacios para que se alinearan correctamente en SE; es convencional usar un ancho de pestaña de 8 para INTERCAL. He probado una versión del programa con todas las pestañas, espacios , y las nuevas líneas eliminadas, sin embargo, y funciona bien).
Compilar con -abm
(penalización de 2 bytes, porque -b
se requiere que el compilador sea determinista).
Como de costumbre para INTERCAL, esto toma la entrada numérica en el formato, por ejemplo, ONE TWO THREE
para 123
.
Explicación
Cuando un programa C-INTERCAL falla, el estado de salida es el código de error módulo 256. Como resultado, podemos apuntar a escribir un programa que sea capaz de producir tantos errores de tiempo de ejecución como sea posible. Este programa solo omite dos errores de tiempo de ejecución que no indican problemas internos del compilador: ICL200I, porque su reproducción requiere el uso de bibliotecas externas que solo son compatibles con un programa de subproceso único (y los programas multiproceso tienen más errores disponibles); e ICL533I, porque 533 tiene el mismo módulo de valor 256 que 277, y el programa es capaz de producir ICL277I.
El programa siempre comienza de la misma manera. Primero, ingresamos ( WRITE IN
) un valor para la variable .1
. Luego, usamos una CREATE
declaración calculada para crear una nueva sintaxis (aquí, A
); pero debido a que se calcula, la definición de la sintaxis varía según el valor de .1
. Finalmente, en la mayoría de los casos ejecutamos nuestra nueva A
declaración, que se ha definido para producir un error; La tabla de posibles definiciones que tenemos contiene una definición para cada posible error de tiempo de ejecución (que no sean las excepciones enumeradas anteriormente).
Primero, hay dos excepciones a este esquema general. (0)
no es un número de línea válido, por lo que si el usuario ingresa ZERO
, saltamos de la segunda línea (numerada (8)
) a la cuarta línea por medio de una COME FROM
declaración calculada . Esto luego cae en un error de sintaxis DO X
, que produce un error ICL000I
. (En INTERCAL, los errores de sintaxis ocurren en tiempo de ejecución, debido a la tendencia de los comandos a deshabilitarse, a redefinirse la sintaxis, etc.). La COME FROM
declaración también tiene un efecto secundario, incluso si no hay real COME FROM
ocurre, la creación de una sobrecarga operando a partir .1
de #1
cada vez que se ejecuta una línea con un número de línea; esto se usa más adelante cuando se produce la salida 21. (Los efectos secundarios globales aleatorios son bastante idiomáticos en INTERCAL).
La otra excepción es con entrada ONE TWO NINE
. No hay un número de línea (129)
en el programa, por lo que obtenemos un error para un número de línea faltante, que es ICL129I
. Así que no tuve que escribir ningún código para cubrir ese caso en absoluto.
Aquí están los otros errores y lo que los causa:
- 123 es un
NEXT
desbordamiento de pila ( DO (123) NEXT
). La NEXT
declaración necesita otros modificadores ( FORGET
o RESUME
) para determinar retroactivamente qué tipo de declaración de control era. No tener esas causas causa el error ICL123I una vez que hay 80 sentencias `NEXT 'sin resolver.
- 222 es un desbordamiento de alijo (
DO STASH .2
en un COME FROM
bucle). Las reservas están limitadas solo por la memoria disponible, pero eventualmente se agotará, causando el error ICL222I.
- 240 es dimensiones de una matriz a tamaño cero. Eso es exactamente lo que
DO ,1 <- #0
significa, y causa el error ICL240I.
- 241 es causado por la asignación fuera de los límites de una matriz. En este caso,
,1
no se ha asignado ( ,
se usa para variables de tipo matriz en INTERCAL), por lo que la indexación causa el error ICL241I.
- 19 asigna 65536 (
#256 $ #0
) a una variable de 16 bits .2
. No encaja, causando el error ICL275I.
- 21 asigna
#2
a .1
. Puede parecer una tarea lo suficientemente simple, pero sobrecargamos .1
para significar #1
antes, e intentar cambiar el valor de 1 sin -v
opción en la línea de comando causa el error ICL277I.
- 148 intenta regresar a la entrada superior de la pila de puntos de elección (
GO BACK
), que no existe en este punto del programa (no hemos ejecutado ningún comando para manipular la pila de puntos de elección, por lo que todavía está vacía). Eso causa el error ICL404I.
- 180 intentos
RETRIEVE .2
de un alijo inexistente (porque no escondimos nada allí en esta rama del programa), causando el error ICL436I.
- 50 solicitudes input (
WRITE IN
) para siempre en un COME FROM
bucle. Eventualmente terminaremos leyendo más allá de EOF, causando el error ICL562I.
- 109 ejecuta la declaración
DO RESUME #0
, que no tiene sentido y está documentada específicamente como causante de un error (ICL621I).
- 120 ejecuta la declaración
DO RESUME #9
. Todavía no hemos ejecutado tantas NEXT
declaraciones y, por lo tanto, tenemos el error ICL120I. (Curiosamente, este error particular se define en la documentación de INTERCAL como salir del programa normalmente y luego causar el error, en lugar de salir del programa con un error. Sin embargo, no creo que estos dos casos sean notablemente diferentes).
- 223 es básicamente una maraña compleja de primitivas de subprocesos múltiples que apuntan de nuevo a la línea 223, causando un bucle infinito que explota la memoria. Finalmente, hay agotamiento de memoria en el subsistema de subprocesos múltiples, lo que lleva al error ICL991I.
- 121 es en realidad una declaración válida (es un comentario), pero aparece al final del programa. Como tal, la ejecución se cae al final del programa inmediatamente después de que se ejecuta, causando el error ICL633I.
Verificación
Algunos de los errores implican ejecutar intencionalmente el programa sin memoria, por lo que sugiero establecer límites de memoria bastante pequeños. Aquí está el comando de shell que usé para probar el programa (con nuevas líneas agregadas para facilitar la lectura; elimínelas si lo ejecuta usted mismo):
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
Y aquí está la salida (con los números de línea y los mensajes "POR FAVOR CORREGIR FUENTE" eliminados para ahorrar espacio), que agregué en parte para demostrar que el programa funciona pero principalmente para mostrar los tontos mensajes de error de 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