chibi-scheme源码阅读4
有点想一口气把这些东西都做完的意思。继续分析chibi-scheme中的ast类型。这一次是介绍:
cnd 类型
在sexp.h
中的sexp_struct
里能找到cnd类型的定义:
1 | struct { |
cnd 类型对应的语法就是if语句的语法,if语句的示例如下:
1 | > (if (= 3 2) 5 10) |
解析获取cnd数据的主要函数是analyze_if
,主要的语句是
1 | test = analyze(ctx, sexp_cadr(x), depth, 0); |
就是将if语句中的每一个部分都拿出来之后解析,并且判断没有出错,将没有出错的它们分别放到一个cnd语句的test、pass和fail的部分中。最后调用了一个make_sexp_cnd
函数以构造一个cnd数据,就是给res里面直接放上test、pass和fail。
set 类型
set类型的定义如下:
1 | struct { |
与set ast类型相通的是 eval.c
里面的 analyze_set
函数。set语句的作用是更改已定义变量的值,因为它不太符合函数式编程在一次运行结束之后不会对其他内容造成影响的原则。所以在实际使用的时候后面是有一个!
,用于说明这个函数改变了变量的值。set的使用如下:(在chibi-scheme的解释器中)
1 | > (define a 3) |
在analyze_set
中,去掉gc相关的内容后,首先是检查set!
列表中的每一项:如果甚至不满足要求,就会给出一个 bad set! syntax
的编译错误。
1 | > (set!) |
然后是判断set!的参数ref原本指向的对象是不是一个lambda表达式,如果是需要进行一个特殊的操作:将lambda表达式的保护变量给保护起来(确保不会被gc回收)。检测一下错误之后,函数就调用了sexp_make_set
,构造了一个set 类型的变量,并将本身作为 source属性给存储了起来。
在set之后有一个set_syn类型,定义与set类型一样。但是我实在看不出在哪里使用过它,所以现在略过了。
ref类型
ref类型的定义如下:
1 | struct { |
使用它的例子如下:
1 | > (let ((x 3)) x) |
其函数为analyze_var_ref
。其内部极为简单,在检查了一下错误后、分配了一个cell类型变量,随后调用sexp_make_ref
构造一个ref类型的变量。
这其中比较麻烦的是获取cell的过程。因为我们需要将在ref语句中的变量临时换为新的值。这一个过程首先需要找出之前环境中可能存在的同名的变量、然后是创建一个新的环境:把新的引用放进去。
seq 类型
seq类型的定义如下:
1 | struct { |
我们可以这样使用seq类型,对应的begin关键字说明的是这些语句会被顺序执行,并返回最后一个语句的结果作为整个语句的结果。
1 | > (begin |
对应的函数analyze_seq
就是直接调用了一下analyze_list
函数。在analyze_list
函数中会遍历整个sexp,依次调用语法分析的总体analyze
函数。这会执行其中的内容,并且把运行的最后一个结果返回。这个调用结果会在之后的sexp_make_seq
函数中被seq放到ls里面。
总结
后面的lit类型,由于它只出现在analyze
的判断中,因此略过了。
到此为止,对于chibi-scheme中的ast类型,已经逐一进行了说明和讲解。下面将会介绍一下chibi-scheme中的一些语句的解析。