有点想一口气把这些东西都做完的意思。继续分析chibi-scheme中的ast类型。这一次是介绍:

cnd 类型

sexp.h中的sexp_struct里能找到cnd类型的定义:

1
2
3
struct {
sexp test, pass, fail, source;
} cnd;

cnd 类型对应的语法就是if语句的语法,if语句的示例如下:

1
2
> (if (= 3 2) 5 10)
10

解析获取cnd数据的主要函数是analyze_if,主要的语句是

1
2
3
4
5
6
7
test = analyze(ctx, sexp_cadr(x), depth, 0);
pass = analyze(ctx, sexp_caddr(x), depth, 0);
fail_expr = sexp_pairp(sexp_cdddr(x)) ? sexp_cadddr(x) : SEXP_VOID;
fail = analyze(ctx, fail_expr, depth, 0);
res = (sexp_exceptionp(test) ? test : sexp_exceptionp(pass) ? pass :
sexp_exceptionp(fail) ? fail : sexp_make_cnd(ctx, test, pass, fail));
if (sexp_cndp(res)) sexp_cnd_source(res) = sexp_pair_source(x);

就是将if语句中的每一个部分都拿出来之后解析,并且判断没有出错,将没有出错的它们分别放到一个cnd语句的test、pass和fail的部分中。最后调用了一个make_sexp_cnd函数以构造一个cnd数据,就是给res里面直接放上test、pass和fail。

set 类型

set类型的定义如下:

1
2
3
struct {
sexp var, value, source;
} set;

与set ast类型相通的是 eval.c里面的 analyze_set函数。set语句的作用是更改已定义变量的值,因为它不太符合函数式编程在一次运行结束之后不会对其他内容造成影响的原则。所以在实际使用的时候后面是有一个!,用于说明这个函数改变了变量的值。set的使用如下:(在chibi-scheme的解释器中)

1
2
3
4
> (define a 3)
> (set! a 10)
> a
10

analyze_set中,去掉gc相关的内容后,首先是检查set!列表中的每一项:如果甚至不满足要求,就会给出一个 bad set! syntax的编译错误。

1
2
> (set!)
ERROR on line 9: bad set! syntax: (set!)

然后是判断set!的参数ref原本指向的对象是不是一个lambda表达式,如果是需要进行一个特殊的操作:将lambda表达式的保护变量给保护起来(确保不会被gc回收)。检测一下错误之后,函数就调用了sexp_make_set,构造了一个set 类型的变量,并将本身作为 source属性给存储了起来。

在set之后有一个set_syn类型,定义与set类型一样。但是我实在看不出在哪里使用过它,所以现在略过了。

ref类型

ref类型的定义如下:

1
2
3
struct {
sexp name, cell, source;
} ref;

使用它的例子如下:

1
2
> (let ((x 3)) x)
3

其函数为analyze_var_ref。其内部极为简单,在检查了一下错误后、分配了一个cell类型变量,随后调用sexp_make_ref构造一个ref类型的变量。

这其中比较麻烦的是获取cell的过程。因为我们需要将在ref语句中的变量临时换为新的值。这一个过程首先需要找出之前环境中可能存在的同名的变量、然后是创建一个新的环境:把新的引用放进去。

seq 类型

seq类型的定义如下:

1
2
3
struct {
sexp ls, source;
} seq;

我们可以这样使用seq类型,对应的begin关键字说明的是这些语句会被顺序执行,并返回最后一个语句的结果作为整个语句的结果。

1
2
3
4
5
6
> (begin
(write-string "Hello!")
(write-string "I am Ciaran")
(+ 4 6)
)
Hello!I am Ciaran10

对应的函数analyze_seq就是直接调用了一下analyze_list函数。在analyze_list函数中会遍历整个sexp,依次调用语法分析的总体analyze函数。这会执行其中的内容,并且把运行的最后一个结果返回。这个调用结果会在之后的sexp_make_seq函数中被seq放到ls里面。

总结

后面的lit类型,由于它只出现在analyze的判断中,因此略过了。

到此为止,对于chibi-scheme中的ast类型,已经逐一进行了说明和讲解。下面将会介绍一下chibi-scheme中的一些语句的解析。