在Swift中实现编程语言—第8部分:函数
注意:这是“用Swift编写编程语言”教程系列的第八部分。一定要检查一下 以前的内容 。
在先前的教程中,我们已经实现了一个小计算器解释器,该解释器支持变量声明和表达式。
下一个要添加的功能是对功能的支持,在本教程中,我们将介绍功能支持的陷阱,并讨论如何实现它。
设计功能声明
过去,某些编程语言在函数定义方面颇具创意。 从Objective-C:
//实例
-(无效)myMethod:(字符串)参数
// 静态的
+(无效)myStaticMethod:(字符串)参数
要使用JavaScript的箭头功能:
(参数)=> {...}
但是自C语言以来,大多数编程语言都是相当传统的语言,并遵循C样式定义:
:: = (){}
其中, 导致某些字符序列(一个单词)。
那么……我们的功能应该如何?
通常,在实现一种语言时,我们希望在创造性和传统方法之间找到一个甜头。 我们希望使用我们的语言的程序员可以谈论一些话题,同时又希望我们的语言直观易读。
但是,由于我们出于教学目的而设计语言,因此我们只是希望事物尽可能直接和传统。 因此,我们语言中的函数看起来与传统的C样式函数定义非常相似:
函数someFunction(firstArgument,secondArgument){...}
我们的语言没有类型检查,因此我们将使用关键字“ function”来标记函数定义的开始,而不是在参数列表中使用传统的返回类型和跳过类型规范。 最后,我们在函数的代码块周围使用匹配的大括号。
实施思路
在上一教程中,我们讨论了添加对变量的支持,事实证明这很简单,只需四个简单步骤:
- 我们为变量声明添加了一个
struct
- 我们在解析器中添加了一个parse方法来创建该结构的实例
- 我们为变量及其值添加了全局内存存储(一个简单的字典)
- 我们实现了该结构的解释过程,该过程简单地存储了变量声明的表达式的解释值,并使用变量名作为键将其存储在我们的全局变量字典中。
我们可以用不到50行的代码来完成所有这些工作。 添加功能是一个相似的过程,但是在内存存储方面有两个主要区别(3)。
- 我们将需要字典将其映射到
Node
值而不是当前Float
,以便可以懒惰地评估该节点。 - 处理变量时,我们的内存存储区必须牢记范围。
范围处理
当涉及范围处理时,有两种方法值得一提。 我们可以有词汇范围或动态范围 。
词汇范围
这是大多数编程语言所使用的。 在词法作用域中 ,变量的解析取决于它们在源代码中的位置。
动态范围
对于动态范围,变量的解析取决于运行时的用法:
var x = 1
函数getX(){
返回x
}
函数some(){
var x = 3
返回getX()
}
//使用动态范围设定,应输出3。
//但是具有词法作用域1。
一些()
总有捷径
我们可以选择词法作用域还是动态作用域,但是为了使事情简单起初,我们将采用仅支持全局变量的第三种选择,如果用户(程序员)试图声明一个变量,则只会引发运行时错误。与现有的标识符。
敬请期待下周,我们终于可以脏手了,写些雨燕!