今天和 claude 一起研究了一下 https://github.com/matz/spinel ,大概知道了它和別的靜態語言有什麼不同。
spinel 的特點是需要對整個程序進行類型推斷,也就是一個方法的類型,實際上是由所有 call site 決定的。當看到一個方法調用的時候,分析器會把參數的類型記下來,然後把它疊到方法的定義上。例如一個方法factorial(n),當分析器看到factorial(1) factorial(2)的時候,它就知道 factorial 能接受 integer,如果整個程序都沒有傳別的類型,那麼它就能斷定 n 是 integer,然後可以輸出很高效的 c 代碼。但如果分析器之後看到 factorial('1'),n 就會變成 integer | string,會需要額外處理多態,實際生成的 c 代碼就會包含這部分的處理。
這樣做的後果是,整個程序如果變了一行,之前的推導就要全部重新來過,因為這個是基於整個程序的推導。其他靜態語言由於會聲明函數的類型,推導對於函數體內和函數外是獨立的,因此一個函數在編譯了之後,如果簽名沒變就可以一直用,可以做到增量編譯。
crystal 實際上也是用整個程序做推斷的,所以會有和 spinel 一樣的侷限,沒辦法做增量編譯。