LiutCL
LiutCL copied to clipboard
主动挖坑并打算努力填坑的一个简陋的Lisp解释器
示例代码如下 ```shell ➜ bin git:(develop) ./liutcl.ros 233-USER> (defvar *a* 1) 233-USER> *a* 1 233-USER> (setf *a* (+ *a* 1)) 找不到标识符*A*的定义 ```
示例代码如下 ```shell ➜ bin git:(develop) ./liutcl.ros 233-USER> (defvar *a* 1) 顶层语句只能是 DEFUN 或 LABELS:(DEFVAR *A* 1) ```
类型Environment,实际上是struct environment_t *的别名,声明于decls.h文件,定义于env_types.h文件中,作用是作为外部环境,提供从符号对象到对应的值之间的映射,即绑定(Binding)。目前的设计是 ``` struct environment_t { SymValMap map; Environment next_env; }; ``` 成员变量map指向一个单链表,SymValMap是为了存储符号到值的映射而实现的类型,因此map相当于指向了一个关联列表(A-list);成员变量next_env指向外部环境,即创建当前环境时已经存在的一个Environment对象。 之所以这么设计,是为了可以方便在一个环境中增加绑定,即为新的符号添加其和一个值的绑定。如果直接使用map所指向的列表来实现环境,那么在一次对set!调用的解释过程中,就需要修改传入的参数并使之成为传出参数,这要求将eval_sexp函数的Environment类型参数修改为二重指针,不方便维护。
symbol-value和symbol-function属于依附于一个符号的内容,它们不是环境的一部分,而是符号的一部分。如果要实现完整的Common Lisp,那么动态作用域是必不可少的,因此let可能就无法简单地实现为lambda的语法糖了。 flet可以局部重定义一个在全局定义的同名函数,可是它所改变的不是一个符号对应的symbol-function成员,而是#',即特殊操作符function所得到的结果。因此,function应该是一种在函数环境中查找一个符号对应的函数体的方式,而一般的变量则是由另外的机制进行查找,但它们有两个环境——一个对应lexical scope,一个对应dynamic scope。 Lisp-1与Lisp-2的区别,和词法作用域与动态作用域的区别,是完完全全的两回事。
``` ● ./lt LiutCL> (car nil) zsh: segmentation fault ./lt ● ./lt LiutCL> (cdr nil) Encounter a null pointer ``` car和cdr空表时,都会段错误。 事实上,nil应该等同于空表。
提示 In function make_object: 0 0 而不是自动退出.
好吧,我水了...