Anda terlalu menyederhanakan pernyataan Guido dalam mengungkapkan pertanyaan Anda. Masalahnya bukan menulis kompiler untuk bahasa yang diketik secara dinamis. Masalahnya adalah menulis yang (kriteria 1) selalu benar, (kriteria 2) terus mengetik dinamis, dan (kriteria 3) terasa lebih cepat untuk sejumlah kode yang signifikan.
Sangat mudah untuk mengimplementasikan 90% (kriteria gagal 1) dari Python dan secara konsisten cepat dalam hal itu. Demikian pula, mudah untuk membuat varian Python yang lebih cepat dengan pengetikan statis (kriteria 2 gagal). Menerapkan 100% juga mudah (sejauh menerapkan bahasa yang kompleks itu mudah), tetapi sejauh ini setiap cara mudah untuk mengimplementasikannya ternyata relatif lambat (kriteria 3 gagal).
Mengimplementasikan interpreter plus JIT yang benar, mengimplementasikan seluruh bahasa, dan lebih cepat untuk beberapa kode ternyata layak, meskipun secara signifikan lebih sulit (lih. PyPy) dan hanya demikian jika Anda mengotomatiskan pembuatan kompiler JIT (Psyco melakukannya tanpa itu , tetapi sangat terbatas pada kode apa yang bisa mempercepat). Tetapi perhatikan bahwa ini secara eksplisit di luar cakupan, karena kita berbicara tentang statisKompiler (alias di muka). Saya hanya menyebutkan ini untuk menjelaskan mengapa pendekatannya tidak bekerja untuk kompiler statis (atau setidaknya tidak ada contoh tandingan): Pertama-tama harus menginterpretasikan dan mengamati program, kemudian menghasilkan kode untuk iterasi tertentu dari loop (atau kode linier lain) path), kemudian optimalkan itu berdasarkan pada asumsi yang hanya berlaku untuk iterasi tertentu (atau setidaknya, tidak untuk semua iterasi yang mungkin). Harapannya adalah bahwa banyak eksekusi kemudian dari kode itu juga akan cocok dengan harapan dan dengan demikian mendapat manfaat dari optimasi. Beberapa cek (relatif murah) ditambahkan untuk memastikan kebenaran. Untuk melakukan semua ini, Anda memerlukan gagasan tentang apa yang menjadi spesialisasi, dan implementasi yang lambat namun umum untuk kembali. Kompiler AOT tidak memiliki keduanya. Mereka tidak bisa berspesialisasi sama sekaliberdasarkan kode yang tidak dapat mereka lihat (mis. kode yang dimuat secara dinamis), dan mengkhususkan secara sembrono berarti menghasilkan lebih banyak kode, yang memiliki sejumlah masalah (pemanfaatan icache, ukuran biner, waktu kompilasi, cabang tambahan).
Menerapkan compiler AOT yang benar mengimplementasikan seluruh bahasa juga relatif mudah: Menghasilkan kode yang panggilan ke runtime untuk melakukan apa interpreter akan lakukan ketika makan dengan kode ini. Nuitka (kebanyakan) melakukan ini. Namun, ini tidak menghasilkan banyak manfaat kinerja (kriteria gagal 3), karena Anda masih harus melakukan pekerjaan yang sama tidak perlunya dengan penerjemah, kecuali mengirimkan bytecode ke blok kode C yang melakukan apa yang Anda kompilasi. Tetapi itu hanya biaya yang agak kecil - cukup signifikan sehingga layak dioptimalkan dalam penerjemah yang ada, tetapi tidak cukup signifikan untuk membenarkan implementasi yang sama sekali baru dengan masalahnya sendiri.
Apa yang dibutuhkan untuk memenuhi ketiga kriteria tersebut? Kami tidak tahu. Ada beberapa skema analisis statis yang dapat mengekstrak beberapa informasi tentang jenis beton, aliran kontrol, dll. Dari program Python. Yang menghasilkan data akurat di luar lingkup blok dasar tunggal sangat lambat dan perlu melihat keseluruhan program, atau setidaknya sebagian besar. Namun, Anda tidak dapat berbuat banyak dengan informasi itu, selain mungkin mengoptimalkan beberapa operasi pada tipe builtin.
Kenapa begitu? Terus terang, kompiler menghapus kemampuan untuk mengeksekusi kode Python yang dimuat saat runtime (kriteria gagal 1), atau tidak membuat asumsi yang dapat dibatalkan oleh kode Python sama sekali. Sayangnya, itu mencakup hampir semua yang berguna untuk mengoptimalkan program: Global termasuk fungsi dapat dipulihkan, kelas dapat dimutasi atau diganti seluruhnya, modul dapat dimodifikasi secara sewenang-wenang juga, impor dapat dibajak dengan beberapa cara, dll. Sebuah string dilewatkan ke eval
, exec
,, __import__
atau berbagai fungsi lainnya, dapat melakukan semua itu. Akibatnya, itu berarti hampir tidak ada optimasi besar yang dapat diterapkan, menghasilkan sedikit manfaat kinerja (kriteria gagal 3). Kembali ke paragraf di atas.