Saya tidak berencana menulis kompiler dalam waktu dekat; tetap, saya cukup tertarik dengan teknologi kompiler, dan bagaimana hal ini dapat dibuat lebih baik.
Dimulai dengan bahasa yang dikompilasi, sebagian besar kompiler memiliki dua tingkat kesalahan: peringatan dan kesalahan, yang pertama adalah sebagian besar waktu hal-hal non-fatal yang harus Anda perbaiki, dan kesalahan yang menunjukkan sebagian besar waktu bahwa tidak mungkin untuk menghasilkan mesin- (atau byte-) kode dari input.
Padahal, ini adalah definisi yang cukup lemah. Dalam beberapa bahasa seperti Java, peringatan tertentu tidak mungkin dihilangkan tanpa menggunakan @SuppressWarning
arahan. Juga, Java memperlakukan masalah non-fatal tertentu sebagai kesalahan (misalnya, kode yang tidak terjangkau di Jawa memicu kesalahan karena alasan yang ingin saya ketahui).
C # tidak memiliki masalah yang sama, tetapi memang memiliki beberapa. Tampaknya kompilasi terjadi dalam beberapa lintasan, dan lintasan yang gagal akan membuat operan lebih lanjut tidak dieksekusi. Karena itu, jumlah kesalahan yang Anda dapatkan ketika bangunan gagal sering terlalu diremehkan. Sekali jalan mungkin mengatakan Anda memiliki dua kesalahan, tetapi begitu Anda memperbaikinya mungkin Anda akan mendapatkan 26 kesalahan baru.
Menggali ke C dan C ++ hanya menunjukkan kombinasi yang buruk pada kelemahan diagnostik kompilasi Java dan C # (meskipun mungkin lebih akurat untuk mengatakan bahwa Java dan C # berjalan sesuai dengan masing-masing masalah). Beberapa peringatan seharusnya merupakan kesalahan (misalnya ketika tidak semua jalur kode mengembalikan nilai) dan masih merupakan peringatan karena, saya kira, pada saat mereka menulis standar, teknologi kompiler tidak cukup baik untuk membuat semacam ini. memeriksa wajib. Dalam nada yang sama, kompiler sering memeriksa lebih dari standar mengatakan, tetapi masih menggunakan tingkat kesalahan peringatan "standar" untuk temuan tambahan. Dan seringkali, kompiler tidak akan melaporkan semua kesalahan yang dapat mereka temukan segera; mungkin butuh beberapa kompilasi untuk menyingkirkan semuanya. Belum lagi kesalahan cryptic compiler C ++ suka meludah,
Sekarang menambahkan bahwa banyak sistem build dapat dikonfigurasi untuk melaporkan kegagalan ketika kompiler mengeluarkan peringatan, kami hanya mendapatkan campuran aneh: tidak semua kesalahan fatal tetapi beberapa peringatan harus; tidak semua peringatan layak tetapi ada yang secara eksplisit ditekan tanpa menyebutkan keberadaannya lebih lanjut; dan terkadang semua peringatan menjadi kesalahan.
Bahasa yang tidak dikompilasi masih memiliki bagian pelaporan kesalahan buruk. Kesalahan ketik di Python tidak akan dilaporkan sampai kode benar-benar dijalankan, dan Anda tidak pernah dapat benar-benar melakukan lebih dari satu kesalahan pada satu waktu karena skrip akan berhenti dijalankan setelah bertemu satu.
PHP, di sisi lain, memiliki banyak tingkat kesalahan yang signifikan, dan pengecualian. Kesalahan parse dilaporkan satu per satu, peringatan sering kali sangat buruk sehingga harus membatalkan skrip Anda (tetapi jangan secara default), pemberitahuan benar-benar sering menunjukkan masalah logika yang serius, beberapa kesalahan sebenarnya tidak cukup buruk untuk menghentikan skrip Anda tetapi masih lakukan, dan seperti biasa dengan PHP, ada beberapa hal yang sangat aneh di sana (kenapa kita perlu tingkat kesalahan untuk kesalahan fatal yang tidak benar-benar fatal?, E_RECOVERABLE_E_ERROR
saya berbicara dengan Anda).
Tampak bagi saya bahwa setiap implementasi tunggal pelaporan kesalahan kompiler yang dapat saya pikirkan rusak. Ini benar-benar memalukan, karena bagaimana semua programmer yang baik menekankan betapa pentingnya menangani kesalahan dengan benar dan belum bisa mendapatkan alat mereka sendiri untuk melakukannya.
Menurut Anda apa cara yang tepat untuk melaporkan kesalahan kompiler?
Jawaban:
Pertanyaan Anda tampaknya bukan tentang bagaimana kami melaporkan kesalahan kompiler - melainkan tentang klasifikasi masalah dan apa yang harus dilakukan tentang mereka.
Jika kita mulai dengan mengasumsikan, untuk saat ini, bahwa dikotomi peringatan / kesalahan sudah benar, mari kita lihat seberapa baik kita dapat membangun di atasnya. Beberapa ide:
"Tingkat" peringatan yang berbeda. Banyak kompiler semacam ini menerapkan ini (misalnya GCC memiliki banyak switch untuk mengkonfigurasi persis apa yang akan memperingatkan tentang), tetapi perlu bekerja - misalnya, melaporkan keparahan apa peringatan yang dilaporkan, dan kemampuan untuk mengatur "peringatan" adalah kesalahan "untuk peringatan hanya di atas keparahan yang ditentukan.
Klasifikasi kesalahan dan peringatan yang waras. Kesalahan hanya boleh dilaporkan jika kode tidak memenuhi spesifikasi, dan karenanya tidak dapat dikompilasi. Pernyataan yang tidak terjangkau, walaupun mungkin kesalahan pengkodean, harus berupa peringatan , bukan kesalahan - kode tersebut masih "valid", dan ada beberapa contoh yang sah di mana seseorang ingin dikompilasi dengan kode yang tidak dapat dijangkau (misalnya modifikasi cepat untuk debugging, misalnya) .
Sekarang hal-hal yang saya tidak setuju dengan Anda di:
Berusaha ekstra untuk melaporkan setiap masalah. Jika ada kesalahan, itu merusak build. Bangunannya rusak. Build tidak akan berfungsi sampai kesalahan itu diperbaiki. Oleh karena itu, lebih baik melaporkan kesalahan itu segera, daripada "melanjutkan" untuk mencoba dan mengidentifikasi segala sesuatu yang lain "salah" dengan kode. Apalagi ketika banyak dari hal-hal itu mungkin disebabkan oleh kesalahan awal pula.
Contoh spesifik Anda tentang peringatan-yang-seharusnya-menjadi-kesalahan. Ya, itu mungkin kesalahan programmer. Tidak, itu seharusnya tidak merusak bangunan. Jika saya tahu input ke fungsi sedemikian rupa sehingga akan selalu mengembalikan nilai, saya harus dapat menjalankan build dan melakukan beberapa tes tanpa harus menambahkan pemeriksaan tambahan tersebut. Ya, itu harus menjadi peringatan. Dan sangat parah sekali pada saat itu. Tapi itu seharusnya tidak merusak bangunan itu sendiri, kecuali kompilasi dengan peringatan-adalah-kesalahan.
Pikiran?
sumber
Satu masalah yang Anda kemukakan adalah pelaporan kesalahan yang tidak lengkap - misalnya, melaporkan 2 kesalahan, dan ketika Anda memperbaikinya, Anda mendapat lebih banyak.
Ini (sebagian besar) kompromi dari penulis kompiler. Tergantung pada apa kesalahan yang telah Anda buat, itu sangat mudah untuk compiler untuk mulai salah paham apa yang Anda lakukan memiliki cukup parah sehingga mulai melaporkan kesalahan yang memiliki sangat sedikit hubungannya dengan realitas. Sebagai contoh, pertimbangkan salah ketik sederhana di mana Anda memiliki sesuatu seperti
itn x;
bukanint x;
. Kecuali Anda telah melakukan sesuatu yang membuatitn
sesuatu menjadi berarti, ini akan dilaporkan sebagai kesalahan. Sejauh ini tidak masalah, tetapi sekarang pertimbangkan apa yang terjadi selanjutnya - kompiler melihat banyak kode yang mencoba untuk digunakanx
sebagai variabel. Haruskah A) berhenti dan membiarkan Anda memperbaikinya, atau B) memuntahkan 2000 kesalahan tentangerror: "x": undeclared identifier
atau sesuatu pada urutan itu? Pertimbangkan kemungkinan lain:Ini adalah salah ketik yang cukup jelas - jelas itu seharusnya
{
bukan[
. Kompiler dapat memberi tahu Anda bagian itu dengan cukup mudah - tetapi haruskah kemudian melaporkan kesalahan untuk sesuatu sepertix=1;
mengatakan sesuatu sepertierror: statement only allowed inside a function
?Perhatikan bahwa ini bahkan masalah yang cukup sepele - yang jauh lebih buruk mudah ditemukan (terutama, seperti yang kita ketahui, ketika Anda masuk ke templat C ++). Intinya adalah bahwa penulis kompiler biasanya terjebak dengan mencoba kompromi antara melaporkan kesalahan palsu (yaitu, melaporkan sesuatu sebagai kesalahan, meskipun tidak masalah) dan gagal melaporkan kesalahan nyata. Ada beberapa aturan praktis yang harus diikuti untuk menjaga agar tidak melakukan kesalahan yang terlalu jauh di kedua arah, tetapi hampir tidak ada satupun yang mendekati sempurna.
Satu masalah lain yang Anda sebutkan adalah Java dan
@SupressWarning
. Ini sangat berbeda dari yang di atas - itu akan cukup sepele untuk diperbaiki. Satu-satunya alasan itu tidak diperbaiki adalah melakukan hal itu tidak sesuai dengan "karakter" dasar Jawa - yaitu, menurut mereka, "itu bukan bug, itu fitur." Meskipun itu biasanya hanya lelucon, dalam hal ini orang-orang yang terlibat begitu salah arah sehingga mereka benar-benar percaya itu benar.Masalah yang Anda sebutkan dalam C dan C ++ dengan jalur kode yang tidak mengembalikan nilai tidak benar-benar memungkinkan untuk kompiler primitif. Itu untuk memungkinkan selama beberapa dekade kode yang ada , beberapa di antaranya tidak ada yang ingin memperbaiki, menyentuh, atau bahkan membaca. Itu kuno dan jelek tapi berhasil, dan tidak ada yang menginginkan apa pun selain itu untuk terus bekerja. Untuk lebih baik atau lebih buruk, komite bahasa yang cukup banyak terjebak dengan mempertahankan bahwa kompatibilitas, sehingga mereka terus membiarkan hal-hal yang tidak ada yang benar-benar menyukai - tetapi beberapa orang (setidaknya pikir mereka) kebutuhan.
sumber
csc
menyerah.