INTERCAL (C-INTERCAL), 15 kode, 313 + 2 = 315 byte
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
Cobalah online!
Semua spasi putih di sini tidak relevan. (Program asli berisi tab, tapi saya mengonversinya ke spasi sehingga berbaris dengan benar di SE; itu konvensional untuk menggunakan lebar tab 8 untuk INTERCAL. Saya telah menguji versi program dengan semua tab, spasi , dan baris baru dihapus, dan berfungsi dengan baik.)
Kompilasi dengan -abm
(penalti 2 byte, karena -b
diperlukan agar kompiler menjadi deterministik).
Seperti biasa untuk INTERCAL, ini membutuhkan input numerik dalam format, misalnya ONE TWO THREE
untuk 123
.
Penjelasan
Ketika sebuah program C-INTERCAL kesalahan keluar, status keluar adalah kode kesalahan modulo 256. Sebagai hasilnya, kita dapat bertujuan untuk menulis sebuah program yang mampu menghasilkan kesalahan runtime sebanyak mungkin. Program ini hanya menghilangkan dua kesalahan runtime yang tidak menunjukkan masalah kompiler internal: ICL200I, karena mereproduksinya memerlukan penggunaan pustaka eksternal yang hanya kompatibel dengan program berulir tunggal (dan program multithreaded memiliki lebih banyak kesalahan yang tersedia); dan ICL533I, karena 533 memiliki nilai modulo 256 yang sama dengan 277, dan program ini mampu menghasilkan ICL277I.
Program selalu memulai dengan cara yang sama. Pertama, kami memasukkan ( WRITE IN
) nilai untuk variabel .1
. Kemudian, kami menggunakan CREATE
pernyataan yang dikomputasi untuk membuat sintaks baru (di sini, A
); tetapi karena itu dihitung, definisi sintaks bervariasi berdasarkan nilai .1
. Akhirnya, dalam kebanyakan kasus kami menjalankan A
pernyataan baru kami , yang telah didefinisikan untuk menghasilkan kesalahan; tabel kemungkinan definisi yang kami miliki berisi definisi untuk setiap kemungkinan kesalahan runtime (selain dari pengecualian yang tercantum di atas).
Pertama, ada dua pengecualian untuk skema umum ini. (0)
bukan nomor baris yang valid, jadi jika pengguna menginput ZERO
, kami melompat dari baris kedua (bernomor (8)
) ke baris keempat dengan menggunakan COME FROM
pernyataan yang dihitung . Ini kemudian jatuh ke dalam kesalahan sintaks DO X
, yang menghasilkan kesalahan ICL000I
. (Dalam INTERCAL, kesalahan sintaksis terjadi saat runtime, karena kecenderungan perintah untuk dinonaktifkan, sintaks yang akan didefinisikan ulang di bawah Anda, dll.). The COME FROM
pernyataan juga memiliki efek samping, bahkan jika tidak ada yang sebenarnya COME FROM
terjadi, menciptakan kelebihan beban operan dari .1
ke #1
setiap kali baris dengan nomor baris dijalankan; ini digunakan nanti ketika menghasilkan output 21. (Efek samping global acak cukup idiomatis dalam INTERCAL.)
Pengecualian lainnya adalah dengan input ONE TWO NINE
. Tidak ada nomor baris (129)
dalam program ini, jadi kami mendapatkan kesalahan untuk nomor baris yang hilang, yaitu ICL129I
. Jadi saya tidak perlu menulis kode apa pun untuk membahas kasus itu sama sekali.
Berikut adalah kesalahan lainnya, dan apa yang menyebabkannya:
- 123 adalah
NEXT
stack overflow ( DO (123) NEXT
). The NEXT
Pernyataan perlu pengubah lainnya ( FORGET
atau RESUME
) untuk surut menentukan apa jenis pernyataan kontrol itu. Tidak ada yang menyebabkan kesalahan ICL123I setelah ada 80 pernyataan `NEXT yang belum terselesaikan.
- 222 adalah simpanan simpanan (
DO STASH .2
dalam satu COME FROM
lingkaran). Stash dibatasi hanya oleh memori yang tersedia, tetapi itu akan habis pada akhirnya, menyebabkan kesalahan ICL222I.
- 240 adalah dimensi array untuk ukuran nol. Itu persis apa
DO ,1 <- #0
artinya, dan itu menyebabkan kesalahan ICL240I.
- 241 disebabkan oleh menetapkan di luar batas array. Dalam hal ini,
,1
belum dialokasikan ( ,
digunakan untuk variabel tipe array di INTERCAL), jadi pengindeksan ini menyebabkan kesalahan ICL241I.
- 19 menetapkan 65536 (
#256 $ #0
) ke variabel 16-bit .2
. Itu tidak cocok, menyebabkan kesalahan ICL275I.
- 21 ditugaskan
#2
untuk .1
. Itu mungkin terlihat seperti tugas yang cukup sederhana, tetapi kami kelebihan beban .1
berarti #1
sebelumnya, dan berusaha untuk mengubah nilai 1 tanpa -v
opsi pada baris perintah menyebabkan kesalahan ICL277I.
- 148 upaya untuk kembali ke entri teratas stack choicepoint (
GO BACK
), yang tidak ada pada titik ini dalam program (kami belum menjalankan perintah apa pun untuk memanipulasi stack choicepoint, jadi masih kosong). Itu menyebabkan kesalahan ICL404I.
- 180 upaya untuk
RETRIEVE .2
dari simpanan yang tidak ada (karena kami tidak menyembunyikan apa pun di cabang program ini), menyebabkan kesalahan ICL436I.
- 50 permintaan input (
WRITE IN
) selamanya dalam satu COME FROM
lingkaran. Akhirnya kita akan membaca EOF terakhir, menyebabkan kesalahan ICL562I.
- 109 menjalankan pernyataan
DO RESUME #0
, yang tidak berarti dan secara khusus didokumentasikan sebagai penyebab kesalahan (ICL621I).
- 120 menjalankan pernyataan
DO RESUME #9
. Kami belum menjalankan banyak NEXT
pernyataan, dan karenanya kami mendapatkan kesalahan ICL120I. (Yang menarik, kesalahan khusus ini didefinisikan dalam dokumentasi INTERCAL sebagai keluar dari program secara normal dan kemudian menyebabkan kesalahan, alih-alih keluar dari program dengan kesalahan. Namun, saya tidak percaya kedua kasus ini berbeda secara nyata.)
- 223 pada dasarnya adalah jalinan kompleks dari multithreading primitif yang semuanya menunjuk kembali ke garis 223, menyebabkan loop tak terbatas yang meledakkan memori. Akhirnya, ada kehabisan memori di subsistem multithreading, yang mengarah ke kesalahan ICL991I.
- 121 sebenarnya adalah pernyataan yang valid (ini adalah komentar), tetapi muncul di akhir program. Dengan demikian, eksekusi jatuh dari akhir program segera setelah dijalankan, menyebabkan kesalahan ICL633I.
Verifikasi
Beberapa kesalahan melibatkan sengaja menjalankan program kehabisan memori, jadi saya sarankan pengaturan batas memori yang cukup kecil. Inilah perintah shell yang saya gunakan untuk menguji program (dengan baris baru ditambahkan agar mudah dibaca; hapus jika Anda menjalankannya sendiri):
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
Dan inilah hasilnya (dengan nomor baris dan pesan "PLEASE CORRECT SOURCE" dihapus untuk menghemat ruang), yang saya tambahkan sebagian untuk menunjukkan program berfungsi tetapi sebagian besar untuk memamerkan pesan kesalahan konyol 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