自制脚本语言[6.1] 函数

注意
本文最后更新于 2023-07-30,文中内容可能已过时。

本篇来尝试描述一下函数如何实现。

基本内容

langX 代码示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
// 函数声明 
funa => {
	a = 1 ;
	funb();

	// 内置函数调用
	println("funa" + a);
}

funb => (x){
  println("funb: " + a);
  a = 101 ;
}

// call function
funa();

如上所述, langX 使用 函数名称 => (参数列表) {函数体} 的风格来声明一个函数, 读者也可以完全设计出自己想要的语法结构。

主要思路

函数的主要目的基本上是复用,隔离变量等。

为了能实现复用的目的,需要保存函数内部的字节码,以及每次在调用函数的时候需要生成新的变量环境。

变量环境

这里先描述一下笔者所说的变量环境是个什么东西。

笔者曾经在 3.1章节环境与节点运算的值 简单的介绍过这个东西。

笔者在langX里面使用是一个叫做环境的词, 即 Enviroment。里面所有的变量都是使用一个std::map保存的,变量名作为key, 变量值作为value。

在现代编程语言里面,似乎都是使用栈或者数组的方式,他们使用索引作为key, 值为value。

笔者的langX因为经验不足的问题, 并没有做栈上的值, 都是做堆上的值, 栈上保存的都是指针, 这并不是一个好的设计。

内置的数字类型应该保存原值,而不是使用指针的形式。

无论是使用map,还是栈,异或局部变量表等等, 在函数代码真正执行前都应该准备一个新的,以隔离函数内外的变量。

字节码 或者 AST 节点

因为函数需要复用, 所以就需要把函数的执行指令保存起来, 而不是执行一遍就丢掉。

AST节点额外内容

笔者在写langX的时候,会把临时计算的值保存到 AST节点上, 这样就需要在函数执行前,或者执行结束后清掉所有的值, 否则会产生一些未预期的行为。 就是可能会产生一些很难找到原因的,莫名其妙的bug。

另外,这也是一个不好的设计, 完全不推荐使用。

总结

函数上来说, 新的东西不太多, 它更像是一个包装,把之前的东西使用新的方式组合和使用。

0%