这只是一个小短篇,介绍一下chibi-scheme的使用(在C语言里进行编程)。其中很多都是直接翻译的官方文档原文。

make

安装chibi-schem的方式很简单。就是从github上面获得源码之后make即可。

然后将会得到一个名为chibi-run的二进制文件。运行它,这就是一个chibi-scheme的解释器了。

C FFI

chibi-scheme是用C完成的,在其中函数声明时带有SEXP_API字样的,就是chibi-scheme提供给C调用的API。

要将chibi-scheme安装到系统默认的路径中,使用make install

要在C中执行chibi-scheme,需要包含头文件:

1
#include <chibi/eval.h>

且在编译的时候,加上chibi-scheme这个库的引用,比如下面这样:

1
gcc -o test_chibi test_chibi.c -L. -lchibi-scheme

使用chibi-scheme的上下文变量

要执行chibi-scheme相关的内容,首先得创建一个chibi-scheme的上下文变量,当然在最后使用之后还要把它删除掉:

1
2
3
4
5
6
int main(int argc, char** argv) {
sexp ctx;
ctx = sexp_make_eval_context(NULL, NULL, NULL, 0, 0);
// your code here ...
sexp_destroy_context(ctx);
}

使用sexp_load_standard_env加载标准参数env,从预编译的默认值构造特征列表,并加载已安装的初始化文件给version( 应该是该值SEXP_SEVEN),同时创建一个interaction-environment参数并将该参数设置为env本身。

使用sexp_load_standard_ports,来从标准的输入输出错误流中获得current-xxxx-port参数,并将他们与env绑定。

1
2
sexp_load_standard_env(ctx, NULL, SEXP_SEVEN);
sexp_load_standard_ports(ctx, NULL, stdin, stdout, stderr, 1);

执行语句

这之后可以使用已经创建好的上下文变量来声明一些变量了。如同之前我们说的gc里面讲的,我们首先需要声明一些变量,然后声明它们收到保护,然后在函数的最后再把对它们的保护进行移除。

1
2
3
4
5
6
7
8
9
10
void dostuff(sexp ctx) {
/* declare and preserve local variables */
sexp_gc_var2(obj1, obj2);
sexp_gc_preserve2(ctx, obj1, obj2);

// your code here ...

/* release the local variables */
sexp_gc_release2(ctx);
}

然后是在里面可以通过sexp_load加载一个.scm文件的代码,干脆自己手写一行代码并执行,还可以通过手动构造一个表达式来运行他。(这里的代码来源于文档)

1
2
3
4
5
6
7
8
9
10
11
/* load a file containing Scheme code */
obj1 = sexp_c_string(ctx, "/path/to/source/file.scm", -1);
sexp_load(ctx, obj1, NULL);

/* eval a C string as Scheme code */
sexp_eval_string(ctx, "(some scheme expression)", -1, NULL);

/* construct a Scheme expression to eval */
obj1 = sexp_intern(ctx, "my-procedure", -1);
obj2 = sexp_cons(ctx, obj1, SEXP_NULL);
sexp_eval(ctx, obj2, NULL);

输出语句

上面的例子不会给出结果,因为没有调用输出的函数,文档中只说可以在堆栈中看到结果。下面给出在窗口中输出的例子如下:

1
2
3
4
5
6
7
/* eval a C string as Scheme code */
obj1 = sexp_eval_string(ctx, "(current-output-port)", -1, NULL);
// obj1 现在是一个输出流
obj2 = sexp_eval_string(ctx, "(+ 3 2)", -1, NULL);
// obj2 现在是你语句的执行结果
sexp_write(ctx, obj2, obj1);
// 输出语句执行结果到输出流

编译运行后结果如下:

1
2
$ gcc -o test_chibi test_chibi.c -L. -lchibi-scheme && ./test_chibi
5

这个例子的代码参见这里