Designing a Programming Language: I

假设

随着编程语言越来越多,世面上出现了各种不同的范式。即便如此,总体来说编程语言分为两大阵营:静态语言和动态语言。为了避免繁杂的历史问题和任何不必要的进一步分析,本文将会做一系列假设来简化一些事情。其中一个假设就是静态语言总是会被编译成机器码,动态语言总是在解释器中运行,虽然这不总是正确的。

如果验证一门语言是静态的还是动态的呢?在静态语言中,变量和过程有严格的类型定义。尝试访问一个在作用域中不存在的变量将会导致编译时语法错误。在解析语言源代码时,所有变量和函数的位置是由词法位置决定的。即给出相关的作用域范围,就能根据变量定义的顺序找到它。

例如,在 Visual Basic 中定义一个变量:

一个简单的示例如下:

Dim num1, num2 As Integer
Dim text As String

这是静态语言的变量定义原型。当变量首次声明的时候,必须指定它的类型。与之不同的是,动态语言则不需要,下面是一段ECMA脚本:

var num1, num2;
var text;

在这个示例中,没有为这些变量指定任何类型。 你可以赋予变量 num1 任何类型的值。不仅如此,变量声明过程也是完全是没有必要的,动态语言的类型信息存储在值对象中。

除Javascript之外,还有很多流行的动态语言,如:Python, Ruby, Lua, Scheme, Lisp等。除了语法风格和表达程度不一样,其他方面都非常类似,如一致的类型系统。所以动态类型语言还常常被理解成鸭子类型或鸭子语言。

我们在从头开始设计鸭子语言的时候,会遵循这些共同特性。不过我们要时刻告诫自己,从零开始构建一门语言仅仅是一个锻炼,在探索过程中我们将不考虑实用性和可行性,当完成这一过程之后再来考虑其他有用的想法。

在开始之前,我要友好地提醒一下各位读者:接下来的章节可能会包含一些非常复杂的知识,即使我已经尽我所能使用朴素和简单的语言来陈述他们。我建议大家在开始此次『语言设计之旅』之前做一些编程语言设计的调研,之后再继续阅读本文。

语法

现在网上应该很容易就能找到一份关于词法表达式的新手指南、Wiki或者某语言语法向导的完整文档,不过先暂时放下这些让我们继续吧。有时从语法层面来看,设计一门语言好比在参考手册上画线做笔录,但这本手册并不是已经写好存在的,或许还会随时间推移发生变化。我这样解释的目的不是建议你设计的编程语言要被精雕细琢,并且实现多么牛逼的概念。相反,我们应该在每一步都思考是否能改变、扩展,随着时间能否进化。一个任务解决所有的问题是不现实的,我们应该有更多的方法来改变事情并且让我们的努力不会白费。

考虑到这一点,我们将在原子层面梳理一下 鸭子语言 的基本机制,在此同时也会探索事情的本质。我们会挖掘语言的本质,以透辙地理解语言的精粹,如果能这样便足够了。编程语言也是表达作者观点的系统。为了更好的与同行交流,我们需要有共同点。

我们将创建一门非常中立的语言,并使用命令式风格。虽然函数式风格可能会最终渗入,但现在我们的目标是大多数程序员。

从哪里着手呢?我们要找到一个根概念,从 语句 开始吧。操作是由语句组成,给你两个值,把它们相加,然后把结果赋给一个变量。如果一个表达式返回值为 , 则执行一个语句块。对一个表达式求值,然后传参做过程调用等等。