elisp动态作用域的实现

2012-06-05

主要文件在lisp.h和eval.c

symbol对象包含4个域:

name符号名

value值

function函数

plist属性链

隐含一个next域指针,指向下一个symbol

有个全局的obarray,其实就是个vector类型的lisp对象。

符号名通过hash确定在obarray中的哪一个桶,然后根据next域出去找到最终的symbol对象


struct specbinding
{
Lisp_Object symbol, old_value;
specbinding_func func;
Lisp_Object unused;      /* Dividing by 16 is faster than by 12 */
};

全局有个specpdl指向specbinding的数组,specpdlptr指向数组的当前位置

相当于一个栈。通过这个结构体做绑定的。

每进入一个新的作用域,比如(let (x) …),将符号x的旧值放在specpdlptr中存起来

x的新值替换x的symbol对象中原来的value。

当退出作用域的时候用specpdlptr中的值恢复x的原值

elisp中没有环境的概念,就通过全局的obarray寻找符号的值,通过specbinding保存符号在各调用栈上的值


其实本质上就相当于elisp中,仅有一个全局的env,就是obarray。

然后每个符号都有一个值的栈。进放一个作用域就进栈一个值,出作用域时这个值出栈,符号始终绑定到栈顶的值

没有闭包。闭包=代码+环境。这里环境不成立了

emacs的源代码比较乱,文档对于internals的解释也不好。

对照xemacs internals看比较容易看懂。

lisp源代码分析