90分钟实现一门编程语言(极简解释器教程)

2019-12-30 14:54:22王冬梅

一些演示

基本的运算

c#,极简解释器

高阶函数

c#,极简解释器

回顾

小结

除去注释(貌似没有注释-_-),iScheme 的解释器的实现代码一共 333 行——包括空行,括号等元素。

在这 300 余行代码里,实现了函数式编程语言的大部分功能:算术|逻辑|运算,嵌套作用域,顺序语句,控制语句,递归,高阶函数,部分求值。

与我两年之前实现的 Scheme 方言 Lucida相比,iScheme 除了没有字符串类型,其它功能和Lucida相同,而代码量只是前者的八分之一,编写时间是前者的十分之一(Lucida 用了两天,iScheme 用了一个半小时),可扩展性和易读性均秒杀前者。这说明了:

    代码量不能说明问题。 不同开发者生产效率的差别会非常巨大。 这两年我还是学到了一点东西的。-_-

一些设计决策

使用扩展方法提高可读性

例如,通过定义 OrThrows


public static void OrThrows(this Boolean condition, String message = null) {
  if (!condition) { throw new Exception(message ?? "WTF"); }
}

写出流畅的断言:


(a < 3).OrThrows("Value must be less than 3.");

声明式编程风格

以 Main 函数为例:


static void Main(String[] cmdArgs) {
  new SScope(parent: null)
    .BuildIn("+", (args, scope) => (args.Evaluate<SNumber>(scope).Sum(s => s)))
    // Other build
    .BuildIn("empty?", (args, scope) => args.RetrieveSList("empty?").Count() == 0)
    .KeepInterpretingInConsole((code, scope) => code.ParseAsIScheme().Evaluate(scope));
}

非常直观,而且

如果需要添加新的操作,添加写一行 BuildIn 即可。 如果需要使用其它语法,替换解析函数 ParseAsIScheme 即可。 如果需要从文件读取代码,替换执行函数 KeepInterpretingInConsole 即可。

不足

当然iScheme还是有很多不足:

语言特性方面:

    缺乏实用类型:没有 Double 和 String 这两个关键类型,更不用说复合类型(Compound Type)。 没有IO操作,更不要说网络通信。 效率低下:尽管去除尾递归挽回了一点效率,但iScheme的执行效率依然惨不忍睹。 错误信息:错误信息基本不可读,往往出错了都不知道从哪里找起。 不支持延续调用(Call with current continuation,即call/cc)。 没有并发。 各种bug:比如可以定义文本量,无法重载默认操作,空括号被识别等等。