- Mengubah kode Ruby menjadi binary native mandiri, dan menargetkan eksekusi dengan rata-rata geometri sekitar 11,6x lebih cepat dibanding CRuby
miniruby terbaru melalui inferensi tipe pada tingkat seluruh program dan pembuatan kode C
- Pipeline kompilasi mengubah Ruby menjadi teks AST dengan parser berbasis Prism, lalu backend self-hosting melakukan inferensi tipe dan pembuatan kode C, kemudian membuat binary standalone dengan kompiler C standar
- Backend kompiler memiliki arsitektur self-hosting yang ditulis dalam Ruby, dan setelah melalui proses bootstrap,
gen2.c == gen3.c terpenuhi sehingga loop untuk mengompilasi dirinya sendiri tertutup
- Menambahkan optimisasi waktu kompilasi seperti perataan konkatenasi string, value-type promotion, loop-invariant length hoisting, static symbol interning, dan auto-promotion bigint, serta mengurangi ketergantungan runtime eksternal dengan regexp engine bawaan, bigint, dan runtime header tunggal
- Tidak mendukung
eval, metaprogramming, Thread, maupun penanganan encoding umum, tetapi bentuk distribusi yang dapat berjalan tanpa Ruby dan perbedaan performa besar pada workload intensif komputasi menunjukkan sisi praktis kompilasi AOT untuk Ruby
Cara kerja
- Pipeline kompilasi terdiri dari alur yang mem-parsing file Ruby, menserialisasikannya menjadi file teks AST, lalu melalui inferensi tipe dan pembuatan kode C untuk menghasilkan binary native dengan kompiler C standar
spinel_parse menggunakan Prism dan libprism untuk mem-parsing Ruby, dan ketika binary C tidak tersedia, ia memakai jalur alternatif yang menggunakan CRuby dan gem Prism
spinel_codegen berjalan sebagai binary native self-hosted, menerima AST dan melakukan inferensi tipe + pembuatan kode C
- Tahap akhir mengompilasi source C bersama header runtime dengan
cc -O2 -Ilib -lm, dan binary hasilnya dibuat dalam bentuk standalone
Self-Hosting
- Rantai bootstrap ditutup dengan cara membuat AST memakai
CRuby + spinel_parse.rb, lalu membuat gen1.c dan bin1 dengan CRuby + spinel_codegen.rb, kemudian memakai binary yang dihasilkan untuk membuat gen2.c dan gen3.c
gen2.c == gen3.c terpenuhi, yang menandakan bootstrap loop telah tertutup
- Backend
spinel_codegen.rb ditulis menggunakan subset Ruby yang dapat dikompilasi langsung oleh Spinel
- classes,
def, attr_accessor
if/case/while
each/map/select, yield
begin/rescue
- operasi String, Array, Hash, dan File I/O
- Backend tidak memasukkan metaprogramming,
eval, maupun require
Performa dan benchmark
- Pengujian berada pada status 74 lolos, benchmark pada status 55 lolos
- Berdasarkan 28 benchmark, rata-rata geometri sekitar 11,6x lebih cepat dibanding CRuby
miniruby terbaru
- Patokan perbandingan adalah build CRuby
miniruby terbaru tanpa bundled gem, dan bahkan jika dibandingkan dengan patokan yang lebih cepat daripada ruby 3.2.3 sistem, keunggulannya tetap besar pada workload intensif komputasi
-
Performa komputasi
life: 20ms vs 1.733ms, 86,7x lebih cepat
ackermann: 5ms vs 374ms, 74,8x lebih cepat
mandelbrot: 25ms vs 1.453ms, 58,1x lebih cepat
- versi rekursif
fib: 17ms vs 581ms, 34,2x lebih cepat
nqueens: 10ms vs 304ms, 30,4x lebih cepat
tarai: 16ms vs 461ms, 28,8x lebih cepat
tak: 22ms vs 532ms, 24,2x lebih cepat
matmul: 13ms vs 313ms, 24,1x lebih cepat
sudoku: 6ms vs 102ms, 17,0x lebih cepat
partial_sums: 93ms vs 1.498ms, 16,1x lebih cepat
fannkuch: 2ms vs 19ms, 9,5x lebih cepat
sieve: 39ms vs 332ms, 8,5x lebih cepat
fasta: 3ms vs 21ms, 7,0x lebih cepat
-
Struktur data dan GC
rbtree: 24ms vs 543ms, 22,6x lebih cepat
splay tree: 14ms vs 195ms, 13,9x lebih cepat
huffman: 6ms vs 59ms, 9,8x lebih cepat
so_lists: 76ms vs 410ms, 5,4x lebih cepat
binary_trees: 11ms vs 40ms, 3,6x lebih cepat
linked_list: 136ms vs 388ms, 2,9x lebih cepat
gcbench: 1.845ms vs 3.641ms, 2,0x lebih cepat
-
Program nyata
json_parse: 39ms vs 394ms, 10,1x lebih cepat
- perhitungan 1000 digit
bigint_fib: 2ms vs 16ms, 8,0x lebih cepat
ao_render: 417ms vs 3.334ms, 8,0x lebih cepat
pidigits: 2ms vs 13ms, 6,5x lebih cepat
str_concat: 2ms vs 13ms, 6,5x lebih cepat
template engine: 152ms vs 936ms, 6,2x lebih cepat
csv_process: 234ms vs 860ms, 3,7x lebih cepat
io_wordcount: 33ms vs 97ms, 2,9x lebih cepat
Fitur Ruby yang didukung
- Fitur Core mendukung classes, inheritance,
super, mixin include, attr_accessor, Struct.new, alias, konstanta module, dan open classes untuk tipe bawaan
- Control Flow mendukung
if/elsif/else, unless, case/when, pattern matching case/in, while, until, loop, for..in, break, next, return, catch/throw, dan &.
- Blocks mendukung
yield, block_given?, &block, proc {}, Proc.new, -> x { }, method(:name), serta method blok seperti each, map, select, reduce, sort_by, times, upto, downto
- Exceptions mendukung
begin/rescue/ensure/retry, raise, dan kelas exception kustom
- Types mencakup Integer, Float, String, Array, Hash, Range, Time, StringIO, File, Regexp, Bigint, Fiber
- nilai polimorfik ditangani sebagai tagged unions
- menyediakan nullable object types
T? untuk struktur data yang mereferensikan dirinya sendiri
- Global Variables mengompilasi
$name menjadi variabel C statis, dan ketidakcocokan tipe dideteksi saat kompilasi
- I/O mendukung
puts, print, printf, p, gets, ARGV, ENV[], File.read/write/open, system(), dan backtick
String, regexp, symbol, Bigint, Fiber
- Strings menangani string immutable dan mutable, dan
<< otomatis dipromosikan menjadi string mutable sp_String untuk melakukan append in-place O(n)
+, interpolation, tr, ljust/rjust/center, dan method standar bekerja pada kedua representasi string
- Perbandingan seperti
s[i] == "c" dioptimalkan agar langsung mengakses array char sehingga diproses tanpa alokasi
- Konkatenasi seperti
a + b + c + d diratakan menjadi satu pemanggilan sp_str_concat4 atau sp_str_concat_arr, sehingga mengurangi N-1 alokasi
str.split(sep) di dalam loop menggunakan ulang sp_StrArray yang sama, dan pada csv_process terjadi penghapusan 4 juta alokasi
- Regexp menggunakan NFA regexp engine bawaan tanpa dependensi eksternal
- mendukung
=~, $1-$9, match?, gsub, sub, scan, split
- Bigint menggunakan integer presisi arbitrer berbasis mruby-bigint
- dipromosikan otomatis pada pola seperti perkalian berulang dalam loop seperti
q = q * k
- ditautkan sebagai library statis dan hanya disertakan saat benar-benar digunakan
- Fiber menyediakan konkurensi kooperatif berbasis
ucontext_t
- mendukung
Fiber.new, Fiber#resume, Fiber.yield, dan pengiriman nilai
- variabel bebas ditangkap sebagai cell yang dipromosikan ke heap
- Symbols diimplementasikan sebagai tipe
sp_sym yang terpisah dari string
- mempertahankan
:a != "a"
- literal symbol di-intern saat kompilasi menjadi konstanta
SPS_name
String#to_sym memakai pool dinamis hanya saat diperlukan
- hash dengan key symbol memakai
sp_SymIntHash untuk menyimpan key integer secara langsung alih-alih string, sehingga strcmp dan alokasi string dinamis hilang
Manajemen memori dan value type
- Manajemen memori menggunakan mark-and-sweep GC, termasuk size-segregated free lists, non-recursive marking, dan sticky mark bits
- Kelas yang kecil dan sederhana otomatis dipromosikan menjadi value types dan ditempatkan di stack
- syaratnya maksimal 8 field skalar
- tidak ada inheritance
- tidak dimodifikasi melalui parameter
- Alokasi kelas dengan 5 field sebanyak 1 juta kali turun dari 85ms menjadi 2ms
- Program yang hanya memakai value type tidak mengekspor runtime GC sama sekali
Optimisasi
- Berdasarkan inferensi tipe tingkat seluruh program, Spinel menjalankan berbagai optimisasi waktu kompilasi
- Value-type promotion membuat kelas kecil yang immutable menjadi objek stack struct C sehingga menghilangkan overhead GC
- Constant propagation meng-inline konstanta literal sederhana seperti
N = 100 langsung di titik penggunaan tanpa lookup cst_N
- Loop-invariant length hoisting membuat
while i < arr.length menghitung panjang hanya sekali sebelum loop
- jika body mengubah receiver seperti
arr.push, hoist ini dinonaktifkan
- Method inlining menambahkan
static inline pada method pendek non-rekursif dengan 3 statement atau kurang untuk mendorong inlining oleh gcc
- String concat chain flattening mereduksi rantai konkatenasi menjadi satu pemanggilan sehingga pembuatan string perantara hilang
- Bigint auto-promotion otomatis mempromosikan pola penjumlahan self-referential atau perkalian berulang menjadi bigint
- Bigint
to_s memakai mpz_get_str dari mruby-bigint untuk pemrosesan divide-and-conquer O(n log²n)
- Static symbol interning mengubah
"literal".to_sym menjadi konstanta waktu kompilasi SPS_<name>, dan hanya menambahkan pool runtime saat interning dinamis dipakai
- Pada
sub_range, string dengan panjang yang sudah di-hoist memakai sp_str_sub_range_len untuk melewati pemanggilan internal strlen
line.split(",") di dalam loop menggunakan ulang sp_StrArray yang sudah ada
- Dead-code elimination memakai
-ffunction-sections -fdata-sections dan --gc-sections untuk membuang fungsi runtime yang tidak digunakan dari binary akhir
- Iterative inference early exit langsung menghentikan loop fixed-point jika tiga array signature untuk parameter, return, dan ivar tidak lagi berubah
- sebagian besar program konvergen dalam 1–2 iterasi penuh, bukan 4 iterasi
- waktu bootstrap berkurang sekitar 14%
parse_id_list byte walk mengganti parser daftar field AST yang dipanggil sekitar 120 ribu kali saat self-compile dari s.split(",") ke iterasi manual s.bytes[i], menurunkan alokasi per panggilan dari N+1 menjadi 2
- Kode C yang dihasilkan mempertahankan warning-free build pada level warning default, dan harness memakai
-Werror agar regresi langsung terlihat
Arsitektur
- Struktur repositori dibagi menjadi komponen berikut
spinel: skrip wrapper satu perintah berbasis POSIX shell
spinel_parse.c: frontend C 1.061 baris dari libprism ke AST teks
spinel_codegen.rb: backend kompiler 21.109 baris dari AST ke kode C
lib/sp_runtime.h: header library runtime 581 baris
lib/sp_bigint.c: integer presisi arbitrer 5.394 baris
lib/regexp/: regexp engine bawaan 1.759 baris
test/: 74 functional test
benchmark/: 55 benchmark
Makefile: otomatisasi build
- Runtime
lib/sp_runtime.h menempatkan implementasi GC, array/hash/string, dan dukungan runtime lainnya dalam satu file header
- Kode C yang dihasilkan meng-include header ini, dan linker hanya mengambil bagian yang diperlukan dari
libspinel_rt.a
- Parser memiliki dua implementasi
spinel_parse.c menaut langsung ke libprism dan berjalan tanpa CRuby
spinel_parse.rb adalah fallback CRuby yang memakai gem Prism
- Kedua parser menghasilkan output AST yang sama, dan wrapper
spinel memprioritaskan binary C bila memungkinkan
require_relative diselesaikan saat parsing sehingga file yang dirujuk di-inline
Batasan
- No eval:
eval, instance_eval, class_eval tidak didukung
- No metaprogramming:
send, method_missing, define_method dinamis tidak didukung
- No threads:
Thread dan Mutex tidak didukung, hanya Fiber yang didukung
- No encoding: mengasumsikan UTF-8 dan ASCII
- No general lambda calculus: tidak menangani pemanggilan
-> x { } dan [] yang sangat bertingkat
Dependensi dan model eksekusi
- Dependensi saat build adalah library C libprism dan CRuby untuk bootstrap awal
- Tidak ada dependensi runtime, dan binary hasil hanya membutuhkan libc + libm
- Regexp menggunakan engine bawaan sehingga tidak memerlukan library eksternal
- Bigint sudah dibundel, tetapi hanya ditautkan saat benar-benar digunakan
- Prism adalah parser Ruby yang dipakai
spinel_parse
make deps mengunduh tarball gem prism dari rubygems.org dan mengekstrak source C ke vendor/prism
- jika gem prism sudah terpasang, ia akan terdeteksi otomatis
- jalur kustom juga bisa ditentukan dengan
PRISM_DIR=/path/to/prism
- CRuby hanya diperlukan untuk bootstrap awal, dan setelah
make, seluruh pipeline berjalan tanpa Ruby
Riwayat proyek
- Spinel awalnya diimplementasikan dalam C, berukuran 18K lines, dan masih tersisa di branch
c-version
- Setelah itu, proyek melewati branch
ruby-v1 yang ditulis ulang dalam Ruby
master saat ini adalah versi yang kembali ditulis ulang dengan subset Ruby yang dapat self-hosting
Lisensi
- Menggunakan MIT License
- Mengikuti file LICENSE
1 komentar
Komentar Hacker News
Karena ini buatan Matz, rasanya lebih mudah dipercaya karena dia pasti paham betul batasan semantics Ruby
Tesis master saya juga dulu tentang AOT JS compiler, dan memang sempat jalan, tapi akhirnya saya hentikan karena batasan pada data input terlalu besar
Waktu itu para developer JS belum terbiasa disiplin menjaga batasan semacam itu, dan input yang secara inheren tidak bisa diketahui seperti
JSON.parsemenjadi penghambat utamaSekarang, berkat TypeScript, mungkin ini jauh lebih realistis dibanding saat itu
Bahkan kalau hanya melihat lambda calculus umum, batas inferensi tipe sudah jelas, dan pembatasan serupa juga terlihat di paper-paper Matt Might maupun proyek Shed-skin Python
Saya penasaran seberapa sering
eval,send,method_missing, dandefine_methodmuncul di kode Ruby nyata, dan juga bagaimana biasanya input parsing tanpa tipe, misalnya input JSON, ditanganiParsing Ruby bahkan bisa lebih sulit daripada proses translasi itu sendiri, jadi mereka memakai Prism, lalu menghasilkan C sebagai output
Semantics dasar Ruby sendiri sebenarnya tidak sampai sesulit itu untuk diimplementasikan
Sebaliknya, saya sedang berkutat dengan self-hosting AOT compiler lama yang ditulis dalam Ruby murni, dan karena saya ngotot memakai parser buatan sendiri, saya sengaja memilih jalan yang jauh lebih sulit
Saya belajar sejak awal bahwa 80% pertama bisa dibuat asal jalan saja dan ternyata sudah cukup untuk menjalankan banyak kode Ruby, sedangkan “80% kedua” yang benar-benar sulit terkumpul pada hal-hal yang dihilangkan Matz dari proyek ini dan dari mruby, misalnya encoding dan segala fitur pinggiran lain
Jujur saja, Ruby punya cukup banyak fitur yang belum pernah saya lihat dipakai di kode nyata, jadi saya rasa tidak aneh kalau beberapa di antaranya akhirnya deprecated
send,method_missing, dandefine_methodsangat umumBatasannya mirip mruby, dan tetap ada kegunaannya bahkan dengan batasan seperti itu
Dukungan untuk
send,method_missing, dandefine_methodrelatif mudahSebaliknya, dukungan eval() sangat menyakitkan
Namun, porsi besar
eval()di Ruby sebenarnya bisa direduksi secara statis menjadi versi blok dari instance_eval, dan dalam kasus seperti itu AOT compilation jadi cukup mudahMisalnya, kalau string yang masuk ke
eval()bisa diketahui atau diurai secara statis, ruang penyelesaiannya jadi jauh lebih besarDalam praktiknya, banyak penggunaan
eval()itu sebenarnya tidak perlu atau hanya semacam jalan memutar untuk introspection sederhana, jadi bisa ditangani lewat analisis statisDi compiler saya juga, kalau itu menjadi bottleneck, saya akan mulai menanganinya dari sana
Ingestion JSON tanpa tipe kemungkinan besar juga memakai mekanisme seperti itu
Kalau itu semua dibuang, yang tersisa adalah bahasa yang kecil dan mudah dibaca, tidak seketat Crystal dalam typing, tapi juga tidak terlalu bergantung pada metaprogramming seperti Ruby resmi
Jadi potensinya terlihat cukup besar, tapi tetap saja baru bisa dinilai seiring waktu
evalBisa saja tidak dipakai, tapi buat saya itu lebih ergonomic
eval,exec,define_method, serta pola membuat class baru denganClass.newdanStruct.newSebagian besar penggunaannya terkonsentrasi saat boot aplikasi atau ketika file di-
require, jadi dalam beberapa hal itu sudah mirip tahap kompilasiIni adalah sesuatu yang baru saja diumumkan Matz di RubyKaigi 2026
Memang masih eksperimental, tapi dibuat hanya dalam waktu sekitar sebulan dengan bantuan Claude, dan live demo-nya juga berhasil
Namanya diambil dari kucing baru Matz, dan nama kucing itu sendiri berasal dari nama kucing di Card Captor Sakura, yang di sana juga dipasangkan dengan karakter bernama Ruby
Untuk orang seperti Matz, mungkin malah seperti mendorong 100x menjadi 500x
https://en.wikipedia.org/wiki/Spinel
Sepertinya videonya belum live, dan tampaknya sedang diunggah satu per satu ke channel ini
https://www.youtube.com/@rubykaigi4884/videos
Nama proyeknya juga terasa dipilih secara emosional
Ini jelas sangat mengesankan, tapi tampaknya mustahil dipelihara tanpa AI agent
spinel_codegen.rbpanjangnya 21 ribu baris, dan beberapa metodenya sampai bertingkat 15 levelKode compiler memang sulit dibuat indah, tapi bahkan dengan standar itu pun, ini terlihat sangat sulit dikelola oleh manusia
Compiler punya batas subsistem yang jelas dan handoff antartahap yang tegas, jadi justru termasuk salah satu jenis sistem yang paling mudah dibuat modular
Masalahnya biasanya setelah berhasil dibuat jalan, tidak ada waktu lagi untuk refactor, lalu kekotorannya terus menumpuk
spinel_codegen.rbnyaris setingkat eldritch horrorSaat memakai Claude, saya juga selalu mendapatkan spaghetti code seperti ini, jadi saya sempat bertanya-tanya apakah saya melakukan sesuatu yang salah
Tapi setelah melihat bahwa proyek yang benar-benar menarik buatan orang yang saya anggap programmer kelas atas pun kualitas kodenya cukup buruk di beberapa bagian, saya jadi tahu bahwa bukan cuma saya
Misalnya,
infer_comparison_type()bukan contoh terburuk dan juga tidak terlalu sulit dibaca, tapi sebenarnya ada implementasi yang jauh lebih sederhana dan jelas, hanya saja Claude gagal menuju ke sanaKalau operator perbandingan dikumpulkan dalam
Setlalu diproses denganinclude?, hasilnya akan lebih pendek, lebih cepat, lebih mudah dibaca, dan lebih gampang dirawatTapi Claude selalu cenderung jatuh ke rantai if-return, bahkan terkesan asing dengan if-else biasa
Codebase Claude saya juga penuh dengan pola seperti itu, dan sekarang saya sadar saya tidak sendirian
Sebaliknya, file-file lain jauh lebih baik, terutama direktori
lib, yang tampaknya berkorespondensi dengan direktoriextdi repo Ruby utama dan kualitasnya cukup bagusAPI-nya juga jelas dipengaruhi MRI Ruby, dan meskipun implementasinya cukup berbeda, tampaknya Matz mengarahkan agar sebagian API-nya menyerupai API asli sehingga output-nya terasa lebih rapi
[1] https://github.com/matz/spinel/blob/98d1179670e4d6486bbd1547...
Selama tes dan benchmark lolos, saya sudah cukup puas
Tapi saya ragu file raksasa seperti itu mudah ditangani bahkan oleh AI
Saya mencoba membatasi file di bawah 300 baris, dan saya pikir kode yang mudah dipahami manusia juga akan lebih mudah dipahami coding agents
Batasannya katanya seperti ini
No eval:
eval,instance_eval,class_evalNo metaprogramming:
send,method_missing,define_method(dinamis)No threads:
Thread,Mutex(Fiber didukung)No encoding: asumsi UTF-8/ASCII
No general lambda calculus:
-> x { }bertingkat dalam dengan pemanggilan[]Asumsi UTF-8/ASCII secara pribadi bukan batasan besar bagi saya, tapi sisanya tampaknya akan jadi batasan nyata untuk cukup banyak program
Dan untuk menambahkan semua itu lagi tampaknya perlu pekerjaan yang lumayan besar
Sebagai orang yang sudah lama memakai Ruby dan pernah menggunakan semua fitur yang disebutkan itu, justru versi Ruby yang sederhana seperti inilah yang akhirnya saya inginkan setelah sekian lama berevolusi
Lebih sederhana dan lebih mudah dipahami, tapi tetap menyisakan rasa estetika khas Ruby
Sekarang, berkat LLM, produktivitas pembuatan kode sudah begitu tinggi sehingga kita tidak lagi terlalu perlu mengurangi boilerplate lewat metaprogramming demi produktivitas developer seperti dulu
Karena porsi kode yang benar-benar ditulis langsung oleh developer sendiri juga makin berkurang
Sintaksnya mirip dan punya static type system, jadi bisa menghasilkan kode hasil kompilasi yang lebih efisien
evalmenurut saya justru lebih baik, tapi ketiadaan threads dan mutexes terasa sayangTidak adanya
define_methodmasih bisa dimengerti kalau melihat kegunaannyaTapi
senddanmethod_missingumum di library yang sudah ada, dan implementasinya rasanya tidak terlalu sulit, misalnya dengan membangun memory lookup table saat compile timeJadi saya tidak tahu apakah itu sengaja dihilangkan, atau mereka memang belum sampai ke sana
Saya berharap yang kedua, tapi setidaknya untuk saat ini tampaknya sulit dipakai di produksi karena masalah kompatibilitas
Melainkan mengurangi jumlah kode yang perlu dibaca
Ini benar-benar keren, dan saya sudah lama menunggu AOT compiler untuk Ruby
Tapi sayang tidak ada fallback untuk
evalatau metaprogramming, meski tampaknya itu memang keputusan untuk fokus pada subset kecil yang berkinerja tinggiAkan bagus kalau gem yang dibuat dengan AOT compiler ini bisa berinteraksi dengan baik dengan MRI
Untuk sisi packaging atau bundling Ruby standar dan gem, kita masih butuh tebako, kompo, dan ocran, dan dulu juga ada proyek seperti ruby-packer, traveling ruby, dan jruby warbler
Senang ada satu opsi lagi, tapi saya tetap berharap akan muncul solusi pamungkas dengan UX developer yang lebih baik
Karena terlalu lama tidak diperbarui
Saya penasaran kenapa no threads
Ruby scheduler dan implementasi pthread di bawahnya rasanya tetap bisa berjalan baik di ranah C, jadi saya sempat berpikir mungkin tujuannya zero dependency
Kalau bukan extension opsional yang rencananya akan ditambahkan nanti atau sekadar belum diimplementasikan, pilihan ini terasa agak aneh
Kemungkinan besar memang baru belum sampai ke sana
Multithreading memang dari awal sangat sulit dibuat dengan benar
Mengejutkan bahwa ini dibuat hanya dalam waktu sedikit lebih dari sebulan
Apa pun pendapat orang soal AI, di tangan developer yang kuat, itu benar-benar bisa menghasilkan percepatan yang luar biasa
Sementara Matz terasa seperti cukup dengan
gem env|infodanfindKarena ini dibuat oleh Matz, saya penasaran seberapa realistis kemungkinan bahwa ini nantinya menjadi bagian dari Ruby core
Dan kalau itu terjadi, saya juga penasaran seberapa besar ancamannya terhadap Crystal
Karakteristik seperti ini nyaris wajib untuk mengompilasi dan memelihara program besar
Sementara ini hanya subset Ruby yang terbatas, jadi sebagian besar gem Ruby populer kemungkinan tidak akan langsung berjalan apa adanya
Sebagai subset bahasa yang menargetkan kompilasi ke C, ini tampak lebih dekat ke PreScheme
Pada tahap sekarang, saya tidak melihat keduanya bersaing langsung di ranah yang sama
Ruby yang benar-benar penuh hampir pasti tetap membutuhkan JIT
[1]: https://prescheme.org/
Ini semacam momen balas dendam untuk tool seperti Rational Unified Process dan Enterprise Architect
Bedanya cuma, yang datang nanti bukan diagram UML melainkan file markdown
Ini sepertinya akan berguna di area infrastructure tools
Misalnya, bayangkan ada bundler yang ditulis dalam Ruby tapi dikompilasi secara statis, sehingga sekaligus bisa berperan seperti alat instalasi Ruby ala RVM
Buildpack Ruby yang sekarang memang ditulis dalam Ruby, tapi bootstrap-nya harus lewat bash sehingga merepotkan dan memunculkan edge case
CNB ditulis dalam Rust untuk menghindari masalah itu, dan gagasan mendistribusikan single binary tanpa dependency benar-benar sangat kuat