Clem adalah bahasa pemrograman berbasis stack minimal yang menampilkan fungsi kelas satu. Tujuan Anda adalah menulis penerjemah untuk bahasa Clem. Itu harus benar menjalankan semua contoh termasuk dalam implementasi referensi, yang tersedia di sini .
- Seperti biasa, celah standar berlaku.
- Entri terkecil dengan jumlah byte menang.
Bahasa Clem
Clem adalah bahasa pemrograman berbasis stack dengan fungsi kelas satu. Cara terbaik untuk mempelajari Clem adalah dengan menjalankan clem
interpreter tanpa argumen. Ini akan mulai dalam mode interaktif, memungkinkan Anda untuk bermain dengan perintah yang tersedia. Untuk menjalankan program contoh, ketik di clem example.clm
mana contoh adalah nama program. Tutorial singkat ini seharusnya sudah cukup untuk membantu Anda memulai.
Ada dua kelas fungsi utama. Fungsi atomik dan fungsi majemuk. Fungsi senyawa adalah daftar yang terdiri dari fungsi senyawa lain dan fungsi atom. Perhatikan bahwa fungsi gabungan tidak dapat mengandung dirinya sendiri.
Fungsi Atom
Tipe pertama dari fungsi atom adalah konstanta . Sebuah konstan hanyalah sebuah nilai integer. Misalnya, -10. Ketika penerjemah menemukan konstanta , itu mendorongnya ke tumpukan. Jalankan clem
sekarang. Ketik -10
pada prompt. Anda harus melihat
> -10
001: (-10)
>
Nilai tersebut 001
menggambarkan posisi fungsi dalam tumpukan dan (-10)
merupakan konstanta yang baru saja Anda masukkan. Sekarang masukkan +11
saat diminta. Anda harus melihat
> +11
002: (-10)
001: (11)
>
Perhatikan bahwa (-10)
telah pindah ke posisi kedua di tumpukan dan (11)
sekarang menempati posisi pertama. Ini adalah sifat tumpukan! Anda akan melihat bahwa -
itu juga perintah pengurangan. Setiap kali -
atau +
mendahului nomor, mereka menunjukkan tanda nomor itu dan bukan perintah yang sesuai. Semua fungsi atom lainnya adalah perintah . Total ada 14:
@ Rotate the top three functions on the stack
# Pop the function on top of the stack and push it twice
$ Swap the top two functions on top of the stack
% Pop the function on top of the stack and throw it away
/ Pop a compound function. Split off the first function, push what's left,
then push the first function.
. Pop two functions, concatenate them and push the result
+ Pop a function. If its a constant then increment it. Push it
- Pop a function. If its a constant then decrement it. Push it
< Get a character from STDIN and push it to the stack. Pushes -1 on EOF.
> Pop a function and print its ASCII character if its a constant
c Pop a function and print its value if its a constant
w Pop a function from the stack. Peek at the top of the stack. While it is
a non-zero constant, execute the function.
Mengetik perintah saat diminta akan menjalankan perintah. Ketik #
saat diminta (perintah rangkap). Anda harus melihat
> #
003: (-10)
002: (11)
001: (11)
>
Perhatikan bahwa (11) telah digandakan. Sekarang ketikkan %
pada prompt (perintah drop). Anda harus melihat
> %
002: (-10)
001: (11)
>
Untuk mendorong perintah ke tumpukan, cukup lampirkan dalam tanda kurung. Ketik (-)
pada prompt. Ini akan mendorong operator pengurangan ke tumpukan. Anda harus melihat
> (-)
003: (-10)
002: (11)
001: (-)
>
Fungsi gabungan
Anda juga dapat menyertakan beberapa fungsi atom dalam tanda kurung untuk membentuk fungsi majemuk. Ketika Anda memasukkan fungsi gabungan saat diminta, itu didorong ke tumpukan. Ketik ($+$)
pada prompt. Anda harus melihat
> ($+$)
004: (-10)
003: (11)
002: (-)
001: ($ + $)
>
Secara teknis, semua yang ada di stack adalah fungsi majemuk. Namun, beberapa fungsi senyawa pada stack terdiri dari fungsi atom tunggal (dalam hal ini, kami akan menganggapnya sebagai fungsi atom demi kenyamanan). Saat memanipulasi fungsi majemuk pada stack, .
perintah (concatenation) seringkali berguna. Ketikkan .
sekarang. Anda harus melihat
> .
003: (-10)
002: (11)
001: (- $ + $)
>
Perhatikan bahwa fungsi pertama dan kedua pada stack digabungkan, dan bahwa fungsi kedua pada stack datang pertama dalam daftar yang dihasilkan. Untuk menjalankan fungsi yang ada di stack (apakah itu atomik atau gabungan), kita harus mengeluarkan w
perintah (while). The w
perintah akan muncul fungsi pertama pada stack dan jalankan berulang kali selama fungsi kedua pada stack adalah non-nol konstan. Cobalah untuk memprediksi apa yang akan terjadi jika kita mengetik w
. Sekarang, ketik w
. Anda harus melihat
> w
002: (1)
001: (0)
>
Itukah yang kamu harapkan? Dua angka yang duduk di atas tumpukan ditambahkan dan jumlahnya tetap. Ayo kita coba lagi. Pertama kita akan menjatuhkan nol dan mendorong 10 dengan mengetik %10
. Anda harus melihat
> %10
002: (1)
001: (10)
>
Sekarang kita akan mengetikkan seluruh fungsi dalam satu tembakan, tetapi kita akan menambahkan ekstra %
di akhir untuk menghilangkan nol. Ketik (-$+$)w%
pada prompt. Anda harus melihat
> (-$+$)w%
001: (11)
>
(Perhatikan algoritma ini hanya berfungsi jika konstanta pertama pada stack positif).
String
String juga ada. Mereka sebagian besar gula sintaksis, tetapi bisa sangat berguna. Ketika penerjemah menemukan sebuah string, itu mendorong setiap karakter dari yang terakhir ke yang pertama ke tumpukan. Ketik %
untuk menjatuhkan 11 dari contoh sebelumnya. Sekarang, ketik 0 10 "Hi!"
prompt. The 0
akan memasukkan terminator NULL dan 10
akan menyisipkan karakter baru-line. Anda harus melihat
> 0 10 "Hi!"
005: (0)
004: (10)
003: (33)
002: (105)
001: (72)
>
Ketik (>)w
untuk mencetak karakter dari tumpukan hingga kami menemukan terminator NULL. Anda harus melihat
> (>)w
Hi!
001: (0)
>
Kesimpulan
Semoga ini cukup untuk membantu Anda memulai dengan juru bahasa. Desain bahasa harus relatif lurus ke depan. Beri tahu saya jika ada sesuatu yang sangat tidak jelas :) Beberapa hal sengaja dibiarkan kabur: nilai harus ditandatangani dan setidaknya 16 bit, tumpukan harus cukup besar untuk menjalankan semua program referensi, dll. Banyak detail belum diukir di sini karena spesifikasi bahasa lengkap akan sangat besar untuk dikirim (dan saya belum menulis satu pun: P). Jika ragu, meniru implementasi referensi.
sumber
Jawaban:
Haskell,
931921875ini belum sepenuhnya golf tetapi mungkin tidak akan pernah. Meski begitu, ini sudah lebih pendek dari semua solusi lainnya.
Saya akan golf ini lebih cepat.Saya tidak ingin bermain golf lebih dari ini.mungkin memiliki beberapa bug halus karena saya tidak bermain dengan implementasi referensi C.
solusi ini menggunakan tipe
StateT [String] IO ()
untuk menyimpan program clem "runnable". kebanyakan program adalah parser yang mem-parsing "program runnable".untuk menjalankan penggunaan ini
r "<insert clem program here>"
.sumber
Python,
16841281 karakterSelesaikan semua hal dasar golf. Ini menjalankan semua contoh program dan mencocokkan keluaran karakter-untuk-karakter.
Pengujian :
Kumpulkan clemint.py , clemtest_data.py , clemtest.py , dan
clem
biner yang dikompilasi ke dalam direktori dan jalankanclemtest.py
.Perluasan :
Versi yang paling ungolfed adalah yang ini . Ikuti bersama dengan yang itu.
S
adalah tumpukan utama. Setiap item tumpukan adalah 3 daftar, salah satu dari:Untuk konstanta,
f
adalah fungsi yang mendorong konstanta ke stack. Untuk atmosferik,f
adalah fungsi yang mengeksekusi salah satu operasi (misalnya-
,+
). Untuk senyawa,fs
adalah daftar barang.xec
mengeksekusi item. Jika itu adalah konstanta atau atom, itu hanya menjalankan fungsinya. Jika itu adalah senyawa, jika belum ada rekursi, ia menjalankan setiap fungsi. Jadi mengeksekusi(10 20 - 30)
akan mengeksekusi masing-masing fungsi10
,20
,-
, dan30
, meninggalkan10 19 30
di stack. Jika ada rekursi, maka itu hanya mendorong fungsi senyawa ke tumpukan. Misalnya, ketika mengeksekusi(10 20 (3 4) 30)
, hasilnya seharusnya10 20 (3 4) 30
, bukan10 20 3 4 30
.Nesting agak sulit. Apa yang Anda lakukan saat membacanya
(1 (2 (3 4)))
? Solusinya adalah memiliki setumpuk tumpukan. Pada setiap tingkat bersarang, tumpukan baru didorong pada tumpukan tumpukan, dan semua operasi dorong masuk ke tumpukan ini. Lebih lanjut, jika telah ada sarang, maka fungsi atom didorong bukannya dieksekusi. Jadi jika Anda melihat10 20 (- 30) 40
,10
didorong, maka20
, maka tumpukan baru dibuat,-
dan30
didorong ke tumpukan baru, dan)
muncul dari tumpukan baru, mengubahnya menjadi item, dan mendorongnya ke tumpukan satu tingkat ke bawah.endnest()
menangani)
. Itu agak rumit karena ada kasus khusus ketika hanya satu item yang didorong dan kami mendorong kembali ke tumpukan utama. Artinya,(10)
harus mendorong konstan10
, bukan komposit dengan konstanta satu, karena itu-
dan+
tidak berfungsi. Saya tidak yakin apakah ini berprinsip tetapi cara kerjanya ...Penerjemah saya adalah prosesor karakter per karakter - tidak membuat token - sehingga angka, string, dan komentar agak menjengkelkan untuk ditangani. Ada tumpukan terpisah
N
,, untuk nomor yang sedang diproses, dan kapan saja karakter yang bukan nomor diproses, saya harus meneleponendnum()
untuk melihat apakah saya harus terlebih dahulu menyelesaikan nomor itu dan meletakkannya di tumpukan. Apakah kita dalam string atau komentar disimpan oleh variabel boolean; ketika sebuah string ditutup itu mendorong semua jeroan di stack. Angka negatif memerlukan penanganan khusus juga.Itu saja untuk ikhtisar. Sisanya menerapkan semua built-in, dan pastikan untuk melakukan copy mendalam dalam
+
,-
dan#
.sumber
C 837
Terima kasih kepada @ceilingcat untuk menemukan versi yang lebih baik (dan lebih pendek)
Ini memperlakukan semuanya sebagai string sederhana - semua item stack adalah string, bahkan konstanta adalah string.
Cobalah online!
Versi kurang asli dari golf saya (tidak seperti versi golf yang satu ini mencetak tumpukan ketika berakhir jika tidak kosong dan mengambil parameter -e sehingga Anda dapat menentukan skrip pada baris perintah alih-alih membaca dari file):
sumber