Bahasa pemrograman do-it-yourself baru

Halo, Habr! Langsung ke intinya. Saat ini saya sedang membaca "Buku Naga" dan saya sedang mengembangkan kompiler untuk bahasa pemrograman saya yang disebut Lolo (untuk menghormati penguin dari kartun Soviet-Jepang). Saya berencana untuk menyelesaikan dalam setahun jika tidak ada yang sakit. Secara paralel, saya akan memposting kutipan menarik dari pengalaman terjemahan, membangun kode perantara, optimisasi, dll., Well, hari ini saya hanya akan memperkenalkan Anda pada bahasa tersebut. Duduk dan pergi.

Bahasa ini dikompilasi, imperatif, tidak berorientasi objek, semantik telah dihapuskan dengan cerdik dari C dan dilengkapi dengan banyak fitur yang berguna. Mari kita mulai dengan mereka.

Modifikasi semantik


Pointer aman


Anda mungkin berpikir tentang pointer cerdas dari Rust sekarang, tetapi mereka tidak. Dalam bahasa saya, keamanan mengakses memori disediakan oleh dua idiom. Pertama: kurangnya operasi pointer dereferencing. Sebaliknya, ketika mengakses pointer yang dinyatakan, objek itu sendiri disebut. Artinya, Anda bisa dan harus menulis seperti ini:

int # pointer ~~ new int(5) int variable ~ pointer + 7 

Variabel variabel sekarang berisi angka 12. Sekarang Anda melihat sintaksis yang tidak dikenal dan, mungkin, Anda sedikit bingung, tetapi saya akan menjelaskan semuanya dalam perjalanan artikel. Idiom kedua: kurangnya operasi pada pointer. Lagi: semua operasi ketika mengakses pointer, termasuk penugasan, kenaikan dan penurunan dilakukan pada objek. Satu-satunya operasi yang berhubungan langsung dengan pointer adalah penugasan berdasarkan alamat, atau, seperti yang saya sebut, identifikasi. Pada contoh kode di atas, pada baris pertama, tepatnya identifikasi. Setiap pointer dapat diatur ke alamat hanya area memori yang sudah dialokasikan, yang merupakan operasi baru yang dikembalikan. Anda juga dapat meletakkan pointer ke alamat variabel lain yang dialokasikan bahkan di heap, bahkan di stack. Berikut ini sebuah contoh:

 int variable ~ 5 int # pointer ~~ variable 

Di sini "~" adalah operasi penugasan yang biasa. Anda juga dapat mengidentifikasi pointer dengan pointer nol khusus. Karena berfungsi sebagai pointer yang merujuk ke alamat nol. Setelah mengidentifikasi operasi perbandingan dan perbandingan identitas (alamat identik) dengan nol, mereka akan menghasilkan true:

 int # pointer ~~ null if (pointer = null) nop ;; true if (pointer == nul) nop ;; true 

Di sini "=" adalah perbandingan nilai, "==" adalah perbandingan berdasarkan alamat, "nop" adalah operasi kosong, dan setelah ";;" - komentar. Dan ya, null adalah satu-satunya operasi penunjuk yang memungkinkan tanpa memeriksa kompatibilitas tipe.

Dengan demikian, pointer hanya dapat ditugaskan untuk memori yang dialokasikan atau area nol dan tidak dapat dipindahkan ke mana pun. Namun, langkah-langkah ini tidak sepenuhnya melindungi terhadap kesalahan kesalahan segmentasi. Untuk mendapatkannya, cukup ikuti langkah-langkah ini:

 int # pointer1 ~~ new int(5) int # pointer2 ~~ pointer1 delete pointer1 int variable ~ pointer2 ;; segmentation fault! 

Saya pikir semuanya jelas di sini. Tetapi untuk membuat kesalahan seperti itu hanya bisa dilakukan dengan sengaja, dan kemudian, setelah bekerja keras. Lagi pula, operasi penghapusan tidak sama dengan pemulung, hanya saja kurang aman. Berbicara tentang dia ...

Pengumpul sampah


Pengumpul sampah - dia juga seorang pengumpul di Lolo. Mungkin tidak perlu dijelaskan apa itu. Saya hanya bisa mengatakan bahwa itu dapat dinonaktifkan oleh opsi khusus selama kompilasi. Kami menguji program dengan kolektor, semuanya berfungsi sebagaimana mestinya - Anda dapat memasukkan opsi dan mencoba mengoptimalkan program menggunakan manajemen memori manual.

Built-in Array


Meskipun saya mengatakan bahwa semantik bahasa dihapuskan dari C, perbedaannya cukup signifikan. Di sini array adalah pointer. Array memiliki sintaks dan pengalamatan aman mereka sendiri. Tidak, tidak dengan cek jangkauan. Dengan mereka, pada prinsipnya, sulit untuk mendapatkan kesalahan runtime. Ini karena setiap array menyimpan panjang dalam ukuran variabel, seperti di Jawa, dan dengan setiap pengindeksan dari indeks ... ada sisa dari pembagian dengan ukuran ini! Keputusan bodoh, sekilas, sampai kita melihat indeks negatif. Jika Anda menemukan sisa pembagian -1 dengan panjang array, Anda mendapatkan angka yang sama dengan ukuran-1, yaitu elemen yang paling terbatas. Dengan manuver seperti itu, kita dapat mengakses indeks tidak hanya dari awal, tetapi juga dari akhir array. Trik lain adalah dengan melemparkan tipe primitif apa pun ke array byte []. Tetapi bagaimana Anda mendapatkan kesalahan runtime, Anda bertanya? Saya akan meninggalkan pertanyaan ini untuk Anda sebagai teka-teki mudah.

Referensi


Saya tidak tahu pasti apakah standar C saat ini menyertakan tautan, tetapi pasti akan ada di Lolo. Mungkin kurangnya referensi dalam versi C sebelumnya adalah salah satu alasan utama untuk pointer ke pointer. Mereka diperlukan untuk meneruskan argumen ke alamat, untuk mengembalikan nilai dari fungsi tanpa menyalin. Pointer dan array juga dapat dilewatkan dengan referensi (karena ketika melewati nilai, array akan sepenuhnya disalin, dan pointer yang ditetapkan ke lokasi baru oleh operasi ~~ tidak akan menyimpannya).

Multithreading


Segalanya lebih indah dan lebih indah. Saya sudah jatuh cinta dengan bahasa saya. Hobi selanjutnya adalah multithreading. Jujur, saya belum sepenuhnya memutuskan alat apa yang akan disediakan. Kemungkinan besar, kata kunci disinkronkan dengan semua properti ala-Java dan, mungkin, kata kunci bersamaan di depan fungsi-fungsi non-inline, yang berarti "menjalankan fungsi-fungsi ini di thread paralel".

String sebaris


Ini adalah string, bukan string literal, seperti dalam C ++. Setiap baris akan memiliki panjangnya sendiri, pengindeksan akan terjadi dengan mencari sisanya. Secara umum, string dalam Lolo sangat mirip dengan array karakter, kecuali bahwa array tidak memiliki penggabungan melalui "+", animasi melalui "*", dan perbandingan melalui "<" dan ">". Dan karena kita berbicara tentang garis, kita harus menyebutkan karakternya. Simbol dalam Lolo bukan angka, seperti dalam C ++. Dan mereka mengandung bukan satu byte, tetapi 4 untuk karakter DKOTI dan 6 untuk karakter UTF. Saya akan berbicara tentang DKOTI lain kali, tetapi untuk sekarang, ketahuilah bahwa Lolo mendukung karakter dan string dalam dua penyandian. Dan ya, properti panjang bahkan dapat diambil dari konstanta:

 int len ~ "Hello, world!".length ;; len = 13 

Jenis Boolean dengan tiga nilai


Sebagian besar bahasa pemrograman yang memiliki tipe data logis menggunakan logika biner. Tetapi di Lolo itu akan menjadi ternary, atau lebih tepatnya, fuzzy ternary. Tiga nilai: benar - benar, salah - salah dan tidak ada - tidak ada. Sejauh ini saya belum menemukan dalam bahasa operasi yang tidak menghasilkan apa-apa, tetapi saya ingat banyak contoh dari praktik ketika bendera dengan tiga nilai akan sangat berguna. Harus menggunakan enumerasi atau tipe integer. Tidak perlu lagi. Itu hanya nama tipe ini yang tidak bisa saya pilih. Yang paling umum adalah "logis," tetapi terlalu lama. Pilihan lainnya adalah "luk" untuk menghormati Jan Lukasevich, "brus" untuk menghormati N. P. Brusnetsov dan "trit", tetapi secara tegas, jenis ini bukan trit. Secara umum, survei ada di akhir artikel.

Daftar untuk menginisialisasi struktur dan daftar


Jika, setelah mendeklarasikan variabel struktural, letakkan tanda ~ dan buka kurung siku, Anda dapat mengatur nilai bidangnya secara bergantian atau dalam bentuk kamus. Jika Anda melakukan prosedur seperti itu dengan sebuah array, Anda bisa mengatur nilai selnya, hanya tanpa kamus. Tidak ada yang istimewa untuk diceritakan, lihat saja kodenya:

 struct { int i; real r; str s; } variable ~ [ i: 5, r: 3.14, s: "Hello!" ] int[5] arr ~ [ 1, 2, 3, 4, 5 ] 


Kembalikan beberapa nilai dari fungsi


Sama seperti di Go! Anda dapat menulis beberapa nama variabel yang dipisahkan oleh koma dan menetapkan semua nilai yang dikembalikan dari fungsi sekaligus:

 int, real function() { return 5, 3.14 } byte Β§ { int i; real r i, r ~ function } 

Modul bukan header


Semuanya jelas di sini. Alih-alih header C-pemalu - modul dari Jawa.

untuk (item otomatis: array)


Lagi-lagi asli Jawa. Karena kami memiliki array dengan panjang, itu dosa untuk tidak menggunakan ekspresi untuk masing-masing.

Operator seleksi tidak hanya untuk int


Saya tidak tahu tentang Anda, tetapi dalam C dan C ++ saya sangat marah dengan kurangnya kemampuan untuk menggunakan operasi switch-case untuk variabel non-integer. Dan sintaksinya juga membuat marah. Di sini, di Pascal adalah masalah lain. Dan sekarang di Lolo:

 case variable { "hello", "HELLO": nop "world": { nop; nop } "WORLD": nop } 

Operator Pembangkit dan Pembagian


Dan ini dari Python.

 real r ~ 3.14 ** 2 int i ~ r // 3 

Parameter fungsi tupel


Ingat bahwa semua operasi dengan pointer dilarang di Lolo, kecuali untuk identifikasi? Sekarang mari kita ingat bagaimana mengakses parameter fungsi dari daftar parameter panjang variabel. Anda perlu mendeklarasikan pointer ke elemen pertama, dan kemudian meningkat sampai kebenaran memeriksa kembali benar. Anda tidak dapat menambahkan di Lolo. Tapi tidak apa-apa. Setelah semua, daftar parameter di sini disajikan dalam bentuk tuple dengan panjang tetap (tergantung-panggilan), dengan indeks-aman, seperti dalam array. Namanya "?" Pemeriksaan jenis dilakukan hanya untuk parameter yang ditetapkan dalam definisi fungsi. Parameter sisanya ("multi-point") direduksi menjadi tipe apa pun, dan dengan gerakan yang canggung perilakunya tidak ditentukan. Tapi tetap saja, tuple seperti itu jauh lebih aman dan lebih nyaman daripada makro di C.

 void function(...) { if (?.size > 1) { int i ~ ?[0] real r ~ ?[1] } } 

Interval numerik


Dan karakter lain - keluarga jenis interval (rentang, urange, lrange, dll.). Mereka diberikan oleh dua bilangan bulat melalui dua titik (..) dan dapat memotong array dari array, string dari string, secara umum, hal yang berguna, saya pikir.

 int[5] arr ~ [ 1, 2, 3, 4, 5 ] int[3] subarr = arr[1..3] ;; [ 2, 3, 4 ] 

Di operator


Dari Pascal. Bekerja dengan string, array, tuple? dan rentang.

 int[5] arr ~ [ 1, 2, 3, 4, 5 ] if (4 in arr) nop 

Kamus Parameter Fungsi


Jujur, saya sudah bingung bagaimana hal ini disebut dengan benar, dengan itu Anda dapat langsung menentukan argumen fungsi yang tidak murni:

 int pos = str_find(string, npos: -1) 

Opsi default


Dari C ++. Di sini, bahkan sebuah contoh tidak perlu diberikan, dan semuanya jelas.

Pengecualian


Nah, dan di mana tanpa mereka?

 try { raise SEGMENTATION_FAULT_EXCEPTION } except (Exception e) { print(e.rus) } 

Tidak ada lompatan tanpa syarat


Karena pada 2019, menggunakan operator GOTO kematian serupa.

Sintaks


Nah, sedikit pembicaraan tentang sintaksis. Seperti yang Anda perhatikan, titik koma dangkal. Bahasa pemrograman modern melakukannya dengan sangat baik tanpa sumber kesalahan ini. Contohnya adalah Python, Kotlin. Operator panah (->) dikombinasikan dengan operator titik. Saat memanggil fungsi tanpa argumen, tanda kurung adalah opsional. String diberikan dalam angka dan sebaliknya. Operator logis dan bitwise digabungkan. Ada pengubah fungsi untuk tabulasi. Fungsi Bersarang type_of. Dan yang paling penting - multibahasa. Ya, saya akan menduplikasi kata kunci, properti string dan array dan semua pengidentifikasi perpustakaan standar dalam semua bahasa komunikasi internasional, yaitu: Inggris, Rusia, Jepang, Cina, Spanyol, Portugis, Arab, Prancis, Jerman dan Latin.

Faktanya, semua hal di atas tidak termasuk setengah dari kemampuan Lolo. Saya tidak bisa segera mengingat semua fitur-fiturnya. Saya akan menambahkan karena kompiler sudah siap.

Source: https://habr.com/ru/post/id460283/


All Articles