eval 有些複雜, 即笨且忙的我, 可否真的弄清楚寫明白是使人懷疑的. 數組
舉一個測試用例 (cons 2 3), 其返回爲構造的點對 (2 . 3), 則按照上篇所述應該走第三步: 函數
Lisp_Object original_fun = form.car; // 即 cons
Lisp_Object fun = original_fun; // 即 cons
fun = XSYMBOL (fun)->function; // 爲內部函數/特殊操做符 cons 在內部定義的 Lisp_Subr 對象.
if (SUBRP(fun))
... 執行這個內部函數/特殊操做符. 測試
對於一個內部函數/特殊操做符 (primitive/special operator), 內部是用 Lisp_Subr 結構來定義的,
爲研究該結構須要還知道 Lisp_vectorlike 等知識, 因此這裏先簡略一點看. ui
對於內部函數 cons , 對應的 Lisp_Subr 結構大體爲: 指針
Lisp_Subr S_cons = {
min_args = 2, max_args = 2,
func = F_cons, 其它字段暫略.
} orm
這個結構而後被關聯到符號 Lisp_Symbol name="cons" 的 function 域, 這樣在 eval() 中可以
經過 XSYMBOL(fun)->function 獲得該內部函數的 Lisp_Subr 信息. 對象
在 Lisp_Subr 中 min_args, max_args 字段用於指出這個內部函數/特殊操做符的參數數量信息,
(我的理解)基本能夠分做三類:
1. 固定參數數量 min_args >=0, 以及有有限數量的可選參數即 max_args >= min_args.
咱們上面給出的測試用例 (cons 2 3) 就是這種狀況.
2. 具備任意數量的參數的函數. 如 list, + 這樣的函數, 其 max_args = MANY, 表示參數數量沒有
限制, 可是要先求值出來再調用 func.
3. 是特殊操做符, 不對參數求值. 例如 if, and, defalias 的特殊操做符, 其 max_args = UNEVALED,
這些特殊操做符必須不對參數求值, 而是根據 if/and 等特殊操做符的特色, 有條件的對參數求值. ci
第1類的狀況, 如測試用例 (cons 2 3), 對這個內建函數(primitive, built-in function) 的執行過程爲: 文檔
1. 先對參數求值. 僞代碼可描述爲:
for-each (a in args) // 遍歷全部參數.
tem_arr[index++] = eval_sub (a) // 對 a 求值, 並放在一個臨時的參數結果數組中
2. 而後根據參數數量(當前實現支持對 0-8 個參數調用), 調用不一樣的函數形式:
case args-num is 0: val = func();
case args-num is 1: val = func(args[0]);
...
case args-num is 8: val = func(args[1], args[2], ..., args[7]); 源碼
在 Lisp_Subr 中的 function 字段在 cons 例子中所指的函數指針就是 C 語言的函數 F_cons.
經過上述過程, 將 Lisp 的函數最終地調用到 C 的實現.
在 emacs 中 lisp 函數 cons 的對應 C 實現名字實際爲 Fcons, 因爲我有疑似"無下劃線標識符名字
識別精神障礙"病, 因此我給它改爲 F_cons 好識別一些...
調用到的函數 F_cons(car, cdr) 時, 該函數按照文檔和幫助所述構造出點對並返回. 具體該函數的實現,
就不在研究 eval() 的範圍內了, 故而略去.
===
對於任意數量參數的函數, 在 Lisp_Subr 結構中 max_args 值爲 MANY, min_args 可能也有非 0 值
表示須要的最少參數數量. 測試用例:
(+ 1 2 3 4 5 6 7 8 9 10) --- 累加 1~10.
與第1類情形相同的地方是, 這些參數要先求值, 再調用函數. 對參數求值和第1類類似, 調用函數的參數
形式略有差別:
func(int arg-num, Lisp_Object *arg) -- 即參數是用一個數組傳遞的.
===
對於第3種形式, 與1,2 的最大區別是不對參數求值, 測試用例:
(if x -- if (x)
(print "x is true") -- then
(print "x is false")) -- else
當 x 求值爲真的時候, 執行 then 部分的形式; x 爲假的時候, 執行 else 部分的形式.
這個例子也說明了, 爲何不能對參數先求值, 由於若是先打印出 x is true, x is false 就不能
知足這個程序片斷的語義須要了. 爲此, if 才被稱做/實現爲特殊形式, 所謂特殊, 即主要指 "不對
參數求值". (在 SICP 的書上可稱爲正則序 vs. 應用序的對比)
因爲不用對參數求值, 參數可直接使用 list 形式傳遞, 而後在 func 中負責拆解這個 list:
func(args)
F_if 的具體實現部分只好再略去了. (懶, 沒時間, 參見源碼還算不難...)