emacs lisp 求值 eval 研究 (幾何畫板開發筆記 九)

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 的具體實現部分只好再略去了. (懶, 沒時間, 參見源碼還算不難...)

相關文章
相關標籤/搜索