一直想知道如何编写一门脚本语言,现在终于有机会实现了。非常感谢 Thorsten Ball 的大作:Writing An Interpreter In Go 帮助我实现了这个想法!
Go 是一门非常不错的语言,但是为了锻炼一下自己,使用 C++ 实现了书中的想法,项目地址:https://github.com/ivanallen/autumn。
可能你比较好奇为啥这个项目叫 Autumn,因为刚好这个项目是在国庆节开始的,正好是秋天,就以当时的季节命名了。
C++ 是一门非常灵活的语言,正好趁这个小项目,我可以天马行空的实现我的各种想法,应用到工程里。
是的,你还可以做的更多!
因为这个项目用到了一些 C++17 的特性,所以你得安装支持 C++17 的编译器,这里直接升级到 GCC8 就行了。
# CentOS
$ yum install readline-devel.x86_64
$ yum install -y devtoolset-8-toolchain
$ scl enable devtoolset-8 bash
# Ubuntu
$ sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
$ sudo apt-get update -qq
$ sudo apt-get install -qq g++-8
$ apt-get install lib64readline-dev
$ export CXX="g++-8"
$ export CC="gcc-8"
$ make
$ ./autumn eval
然后你就可以在控制台编写一些命令或函数啦!
let map = fn(arr, f) {
let iter = fn(arr, accumulated) {
if (len(arr) == 0) {
accumulated
} else {
iter(rest(arr), push(accumulated, f(first(arr))));
}
};
iter(arr, []);
};
// 压缩成一行的
let map = fn(arr, f) { let iter = fn(arr, accumulated) { if (len(arr) == 0) { accumulated } else { iter(rest(arr), push(accumulated, f(first(arr)))); }}; iter(arr, []);};
let a = [1,2,3,4]
let double = fn(x) { x * 2 };
map(a, double)
let filter = fn(arr, f) {
let iter = fn(arr, accumulated) {
if (len(arr) == 0) {
accumulated
} else {
let e = if (f(first(arr))) {
push(accumulated, first(arr));
} else {
accumulated
}
iter(rest(arr), e);
}
};
iter(arr, []);
};
// 压缩成一行的
let filter = fn(arr, f) { let iter = fn(arr, accumulated) { if (len(arr) == 0) { accumulated } else { let e = if (f(first(arr))) { push(accumulated, first(arr)); } else { accumulated } iter(rest(arr), e); }}; iter(arr, []);};
let a = [1,5,3,6,3,8]
let lessThanFour = fn(x) { x < 4 }
filter(a, lessThanFour)
let quickSort = fn(arr) {
if (len(arr) == 0) {
return arr;
} else {
let head = first(arr);
let smaller = filter(rest(arr), fn(x) { x <= head });
let bigger = filter(rest(arr), fn(x) { x > head });
return quickSort(smaller) + [head] + quickSort(bigger);
}
}
// 一行版本
let quickSort = fn(arr) {if (len(arr) == 0) {return arr;} else {let head = first(arr);let smaller = filter(rest(arr), fn(x) { x <= head });let bigger = filter(rest(arr), fn(x) { x > head });return quickSort(smaller) + [head] + quickSort(bigger);}}