- Pada 1989, High C Compiler untuk FM TOWNS tidak hanya mendukung lingkungan DOS, tetapi juga menyertakan berbagai fitur bahasa yang berorientasi pada pengguna, sesuatu yang langka untuk kompiler C saat itu
- Dikombinasikan dengan DOS extender dari Phar Lap, kompiler ini menjadi bagian dari alur pengembangan yang memanfaatkan 80386 32-bit di lingkungan MS-DOS 16-bit, dan menjadi kompiler C pihak pertama untuk FM TOWNS
- Pemisah garis bawah pada literal angka, argumen berlabel, rentang
case, fungsi bertingkat, dan generator adalah fitur yang masuk ke standar C/C++ jauh lebih lambat, atau bahkan masih belum ada dalam standar - Fungsi bertingkat menyediakan “full function value” dalam bentuk closure non-escaping yang membawa pointer fungsi bersama pointer konteks, sehingga lebih ekspresif daripada pointer fungsi C biasa
- Generator diimplementasikan sebagai gula sintaks di atas fungsi bertingkat, dengan struktur sederhana yang mengubah isi loop
formilik pemanggil menjadi fungsi bertingkat lalu meneruskannya sebagai argumenyield
Posisi FM TOWNS dan High C
- Sebuah manual kompiler C dari era 1980-an yang ditemukan di tumpukan buku terkait FM TOWNS ternyata berisi ekstensi bahasa yang jauh lebih kaya dari perkiraan
- Untuk benar-benar memakai C dan bahasa turunannya di lingkungan nyata, selama bertahun-tahun dibutuhkan ekstensi vendor
- Di lingkungan modern yang berpusat pada GCC, Clang, dan MSVC, ekstensi cenderung terfokus pada penanganan spesifik platform atau kontrol detail tingkat rendah
- Pada 1980-an, lebih banyak perusahaan yang lebih kecil saling bersaing untuk diadopsi, sehingga fitur ekstensi juga jauh lebih beragam
- Phar Lap membuat salah satu DOS extender awal yang memungkinkan pemanfaatan prosesor 80386 32-bit di lingkungan MS-DOS 16-bit
- Atas permintaan Phar Lap, MetaWare mem-porting High C Compiler ke SDK DOS extender milik Phar Lap
- Fujitsu mengintegrasikan DOS extender dari Phar Lap ke dalam OS platform FM TOWNS berbasis 803386, dan High C menjadi kompiler C pihak pertama untuk platform ini
- FM TOWNS dirilis pada 1989, tepat sebelum C89, standar ANSI C pertama, diratifikasi
Fitur-fitur kecil yang mendahului standar
-
Pemisah garis bawah pada literal angka
- Untuk memudahkan pembacaan literal angka yang panjang, pengguna dapat menyisipkan pemisah garis bawah di dalam angka
- C++ memperkenalkan pemisah tanda kutip tunggal seperti
1'000'000di C++14 - C baru memperkenalkan fitur serupa di C23
-
Argumen berlabel
- Nama argumen dapat ditambahkan pada fungsi yang memiliki banyak parameter atau sering memakai tipe seperti
boolyang maknanya sulit terlihat langsung di titik pemanggilan - Argumen berlabel di High C bekerja mirip dengan fitur populer di Python
- Label argumen bersifat opsional
- Jika memakai label, argumen dapat ditentukan dalam urutan bebas dengan sintaks
argumentName => value - Argumen tanpa label dan berlabel dapat dicampur, tetapi semua parameter fungsi tetap harus memiliki argumen yang sesuai
- C dan C++ standar masih belum memiliki fitur ini
- Nama argumen dapat ditambahkan pada fungsi yang memiliki banyak parameter atau sering memakai tipe seperti
-
Rentang
case- Menyediakan kemampuan untuk mencocokkan rentang nilai sekaligus, seperti
case low..highdi Pascal - C dan C++ standar tidak mengadopsi fitur ini
- Menyediakan kemampuan untuk mencocokkan rentang nilai sekaligus, seperti
Fungsi bertingkat dan full function value
- High C memungkinkan deklarasi fungsi bertingkat di dalam fungsi lain, seperti di Pascal
- Cara implementasinya lebih mendekati bentuk yang lengkap dibanding Pascal standar atau ekstensi fungsi bertingkat milik GCC
- High C tidak hanya mendukung deklarasi fungsi bertingkat, tetapi juga dapat mendeklarasikan tipe full function value
- Tidak seperti pointer fungsi C tradisional, tipe ini menyimpan pointer fungsi bersama pointer konteks
- Ini memungkinkan konteks yang ditangkap oleh fungsi bertingkat ditemukan kembali
- Bentuk ini adalah closure non-escaping yang masa hidupnya tidak berlanjut setelah fungsi luarnya mengembalikan hasil
- Ekstensi fungsi bertingkat milik GCC mencoba merujuk fungsi bertingkat sebagai pointer fungsi biasa dengan menulis kode yang dapat dieksekusi ke call stack untuk melakukan thunk pada pointer konteks
- Pendekatan ini menimbulkan risiko keamanan besar dan membuat banyak platform menonaktifkan fitur tersebut sepenuhnya
- Referensi fungsi lokal di High C dapat dipakai seperti nilai kelas satu, tetapi masa hidupnya tidak diperpanjang hingga setelah fungsi luar selesai
- Fungsi bertingkat juga dapat melakukan
gotoke fungsi induknya- Ini memungkinkan pelarian non-lokal ke luar fungsi bertingkat, seperti blok di Smalltalk
- Dengan itu, fungsi dapat dibuat agar bertindak seperti alur kontrol
- Objective-C memperoleh blocks yang dapat dipakai sebagai escaping closure pada 2009, dan C++ memperkenalkan lambda pada 2011
- Keduanya tidak memiliki kemampuan pelarian non-lokal
- C standar masih belum memiliki fitur fungsi bertingkat resmi
Korutin generator
- MetaWare menonjolkan fitur generator sampai mendedikasikan satu bab penuh untuknya
- Pada 1989, High C sudah mendukung korutin generator bergaya Python dalam plain C
- Fungsi generator dideklarasikan dengan sintaks
void foo(Arg arguments) -> (Yield yields)- Di dalam fungsi, pemanggilan berulang ke fungsi ajaib
yield(values...)dapat menghasilkan urutan nilai - Pemanggil menelusuri nilai yang dihasilkan satu per satu dengan sintaks loop
forbaru berbentukfor variable... <- foo(arguments...) do { ... }
- Di dalam fungsi, pemanggilan berulang ke fungsi ajaib
- Implementasi ini dapat dikombinasikan secara rumit dengan fungsi bertingkat
- Fungsi bertingkat di dalam generator dapat menangkap perilaku
yielddari generator luarnya - Fungsi bertingkat dapat memanggil dirinya sendiri secara rekursif untuk menelusuri pohon atau struktur data rekursif sambil melakukan
yielddi setiap langkah
- Fungsi bertingkat di dalam generator dapat menangkap perilaku
- Bentuk seperti ini tampak sulit diwujudkan di Python atau banyak bahasa generator korutin arus utama lainnya
Cara implementasi generator dan perbedaannya dari bahasa standar
- Generator di High C bekerja sebagai gula sintaks di atas fungsi bertingkat tanpa runtime tingkat tinggi
- Deklarasi generator berbentuk
void foo(Arg arguments) -> (Yield yields)setara dengan deklarasi fungsi biasavoid foo(void yield(Yield yields)!, Arg arguments)yieldadalah parameter implisit bertipe “full function value”- Pemanggilan
yield(values)di dalam isi generator hanyalah pemanggilan fungsi biasa terhadap parameter fungsi implisit itu
- Isi loop
fordi sisi pemanggil diubah menjadi fungsi bertingkat- Fungsi bertingkat ini lalu diteruskan sebagai argumen
yieldke generator - Strukturnya sederhana, tetapi efektif
- Fungsi bertingkat ini lalu diteruskan sebagai argumen
- Karena fungsi bertingkat mendukung pelarian non-lokal,
break,continue, dangotoyang keluar dari isi loopforjuga bekerja dengan cara melakukangotoke posisi yang sesuai di luar loop - Kecil kemungkinan C standar akan mencoba mengintegrasikan fitur seperti ini
- C++20 menyediakan fitur korutin yang sangat fleksibel dan kompleks, berbasis transformasi korutin saat waktu kompilasi
- Fitur ini tampaknya dapat dipakai untuk mengimplementasikan generator
- Namun hasilnya kemungkinan tidak akan dapat dipadukan dengan fungsi lokal secara seintuitif ini
1 komentar
Komentar Hacker News
Untungnya saya punya satu eksemplar High C/C++ Language Reference versi bahasa Inggris
http://jdebp.uk./FGA/metaware-iterator-driven-for.html
http://jdebp.uk./Proposals/metaware-iterator-driven-for.html
breakataureturndikompilasi. Apakah mestinya diubah sehingga fungsiyieldmengembalikan kode status lalu diperiksa di titik pemanggilan?case, argumen bernama, fungsi bersarang, fungsi bersarang statis, dan fitur mirip generatorMisalnya bentuk seperti
int a = 1_234_567;,case 5 .. case 6:,test(b:3, a:4);dimungkinkanFungsi bersarang statis tidak bisa mengakses variabel frame dari fungsi luar, sehingga muncul error seperti
Error: static function test.foo.plus cannot access variable i in frame of function test.fooFitur yang mirip generator ada di https://dlang.org/spec/statement.html#foreach_over_struct_an...
Misalnya jika membuat layanan cache in-memory, sebaiknya item cache itu sendiri tidak dilacak oleh garbage collector. Sebab garbage collector sering tidak mengetahui pola akses sebenarnya, sehingga justru bisa mengganggu. Namun sebagian besar komponen lain dalam layanan itu lebih cocok jika ada garbage collector
Mengapa argumen bernama berbentuk
test(a:4, b:3), bukantest(.a=4, b.=3);?Saya juga penasaran bagaimana first-class type bisa ditangani di C
lcc-winmenambahkan operator overloading, argumen fungsi default, dan function overloading. Di dokumentasinya, lihat bagian “generic functions” [1]Compiler C Plan 9 juga memperkenalkan sejumlah ekstensi bahasa, dan sebagian di antaranya, seperti struct/union anonim, kemudian masuk ke standar C. Saat ini GCC menerima flag
-fplan9-extensions[2], yang mengaktifkan fitur-fitur yang cukup berguna, seperti konversi otomatis pointer struct menjadi field anonim dalam pemanggilan fungsi dan assignment[1] https://lcc-win32.services.net/C-Tutorial.pdf
[2] https://gcc.gnu.org/onlinedocs/gcc/Unnamed-Fields.html
Sayang sekali fitur-fitur itu tidak tersebar luas ke dunia dan memengaruhi standar bahasa. Mengejutkan bahwa fitur seperti ini sudah ada sejak lama
Ini juga pernah dibahas di Hacker News: https://news.ycombinator.com/item?id=38938402
Apakah ada salinan PDF-nya di suatu tempat?
yield, pada pertengahan hingga akhir 1970-an [0]. Bahasa Icon dari periode yang mirip juga punya fitur generator serupa [1], dan menyebutyieldsebagaisuspend. Sepengetahuan saya, Ada (1983) juga memiliki fitur seperti iniFitur-fitur bahasa seperti ini bukan sama sekali tidak dikenal
[0] https://publications.csail.mit.edu/lcs/pubs/pdf/MIT-LCS-TR-2...
[1] https://dl.acm.org/doi/pdf/10.1145/800055.802034
Isinya menjelaskan underscore dalam angka, rentang
case, parameter bernama, fungsi bersarang, hingga variabel fungsi penuhhttps://bitsavers.org/pdf/metaware/…
Lihat Appendix A, sekitar 50-an halaman sebelum akhir file
Dulu, saat masih belajar dan menulis kode, saya mengenalnya lewat situs-situs yang agak mencurigakan
Kita juga akan menemukan sejarah yang kaya dari bahasa pemrograman sistem. Terlihat juga betapa miripnya desain C dan Go dalam hal mengabaikan apa yang sedang terjadi di ekosistem lain serta pengalaman masa lalu
Tautan manual kompilernya ada di https://winworldpc.com/product/metaware-high-c-cpp/33x
PDF manual C memiliki keterangan hak cipta tahun 2007
https://f.duriansoftware.com/@joe/113195961485703110
¥n, bukan\n, tampaknya contoh-contoh kode ini ditulis dalam Shift-JIS. Dalam Shift-JIS, posisi\pada ASCII ditempati oleh¥[0] https://en.wikipedia.org/wiki/JIS_X_0201
Untuk penggunaan ini, EUC-JP lebih baik karena tidak punya masalah seperti itu. Di Pascal, jika memakai komentar
(* *)dan tidak memakai komentar{ }, Shift-JIS tidak mengalami masalah iniSebagai gantinya, besar kemungkinan yang dipakai adalah JIS X 0201(https://en.m.wikipedia.org.org/wiki/JIS_X_0201), yang menjadi dasar Shift-JIS
C:¥, bukanC:\Call (Param_A => 1, Param_B => "Foo");, garis bawah pada angka dengan basis sembarang (X : Integer := 1_000;), subprogram bersarang, dan pemeriksaan berbasis rentangKita tampaknya sering lupa bahwa C pada masa itu luar biasa primitif dibanding banyak bahasa lain
Saya tidak cukup paham aturan penulisan Jepang atau kerning, tetapi kelihatannya seperti mereka mengambil font lebar variabel yang memuat kanji dan huruf Latin, lalu memaksanya masuk ke dalam kotak lebar tetap
Bagaimanapun, bagus bahwa contoh kodenya bukan memakai font 8pt seperti banyak buku yang saya punya
try_fold()(https://scribe.rip/@veedrac/rust-is-slow-and-i-am-the-cure-3...)Namun justru karena alasan itu, ekstensi-ekstensi seperti ini relatif tidak dikenal, dan puluhan tahun kemudian harus ditemukan kembali serta diciptakan ulang dalam C/C++ modern