INTERCAL (C-INTERCAL), 15 codes, 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
Try it online!
All whitespace here is irrelevant. (The original program contained tabs, but I converted them to spaces so that it'd line up correctly on SE; it's conventional to use a tab width of 8 for INTERCAL. I've tested a version of the program with all tabs, spaces, and newlines deleted, though, and it works fine.)
Compile with -abm (2 byte penalty, because -b is required for the compiler to be deterministic).
As usual for INTERCAL, this takes numeric input in the format, e.g., ONE TWO THREE for 123.
Explanation
When a C-INTERCAL program errors out, the exit status is the error code modulo 256. As a result, we can aim to write a program that's capable of producing as many runtime errors as possible. This program only omits two runtime errors that don't indicate internal compiler issues: ICL200I, because reproducing it requires the use of external libraries that are only compatible with a single-threaded program (and multithreaded programs have more errors available); and ICL533I, because 533 has the same value modulo 256 as 277 does, and the program's capable of producing ICL277I.
The program always starts the same way. First, we input (WRITE IN) a value for the variable .1. Then, we use a computed CREATE statement to create new syntax (here, A); but because it's computed, the definition of the syntax varies based on the value of .1. Finally, in most cases we run our new A statement, which has been defined to produce an error; the table of possible definitions we have contains a definition for each possible runtime error (other than the exceptions listed above).
First, there are two exceptions to this general scheme. (0) is not a valid line number, so if the user inputs ZERO, we jump from the second line (numbered (8)) to the fourth line by means of a computed COME FROM statement. This then falls through into a syntax error DO X, which produces error ICL000I. (In INTERCAL, syntax errors happen at runtime, due to the tendency of commands to be disabled, syntax to be redefined under you, etc.). The COME FROM statement also has a side effect, even if no actual COME FROM happens, creating an operand overload from .1 to #1 whenever a line with a line number is executed; this is used later on when producing output 21. (Random global side effects are fairly idiomatic in INTERCAL.)
The other exception is with input ONE TWO NINE. There's no line number (129) in the program, so we get an error for a missing line number, which is ICL129I. So I didn't have to write any code to cover that case at all.
Here are the other errors, and what causes them:
- 123 is a
NEXT stack overflow (DO (123) NEXT). The NEXT statement needs other modifiers (FORGET or RESUME) in order to retroactively determine what sort of control statement it was. Not having those causes error ICL123I once there are 80 unresolved `NEXT statements. - 222 is a stash overflow (
DO STASH .2 in a COME FROM loop). The stashes are limited only by available memory, but that will run out eventually, causing error ICL222I. - 240 is dimensions an array to size zero. That's exactly what
DO ,1 <- #0 means, and it causes error ICL240I. - 241 is caused by assigning outside the bounds of an array. In this case,
,1 hasn't been allocated (, is used for array-type variables in INTERCAL), so indexing it causes error ICL241I. - 19 assigns 65536 (
#256 $ #0) to a 16-bit variable .2. It doesn't fit, causing error ICL275I. - 21 assigns
#2 to .1. That might look like a simple enough assignment, but we overloaded .1 to mean #1 earlier, and attempting to change the value of 1 with no -v option on the command line causes error ICL277I. - 148 attempts to return to the top entry of the choicepoint stack (
GO BACK), which doesn't exist at this point in the program (we haven't run any commands to manipulate the choicepoint stack, so it's still empty). That causes error ICL404I. - 180 attempts to
RETRIEVE .2 from a nonexistent stash (because we didn't stash anything there in this branch of the program), causing error ICL436I. - 50 requests input (
WRITE IN) forever in a COME FROM loop. Eventually we'll end up reading past EOF, causing error ICL562I. - 109 runs the statement
DO RESUME #0, which is meaningless and specifically documented as causing an error (ICL621I). - 120 runs the statement
DO RESUME #9. We haven't run that many NEXT statements yet, and thus we get error ICL120I. (Intriguingly, this particular error is defined in the INTERCAL documentation as exiting the program normally and then causing the error, rather than exiting the program with an error. I don't believe these two cases are observably different, though.) - 223 is basically a complex tangle of multithreading primitives that all point back to line 223, causing an infinite loop that blows up memory. Eventually, there's memory exhaustion in the multithreading subsystem, leading to error ICL991I.
- 121 is actually a valid statement (it's a comment), but it appears at the end of the program. As such, execution falls off the end of the program immediately after it executes, causing error ICL633I.
Verification
Some of the errors involve intentionally running the program out of memory, so I suggest setting fairly small memory limits. Here's the shell command I used to test the program (with newlines added for readability; delete them if you run it yourself):
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
And here's the output (with the line numbers and "PLEASE CORRECT SOURCE" messages deleted to save space), which I added partly to demonstrate the program working but mostly to show off INTERCAL's silly error messages:
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
throw new Exception()style), that is illegal. If it is the byproduct of misuse of an existing function, then that's fine. \$\endgroup\$one zero zerofor 100) acceptable? I have an idea for this challenge, but the language has some fairly unusual ideas about I/O, and this is the most natural input format. \$\endgroup\$