一个比较完整的lisp解释器 lua实现
作者:ertuil
时间:2018年2月10日
想法
这两天在看了一些奇怪的书,看完之后突发奇想,就有了这样一个【功能还算完整的】【自创方言的】【函数式】的lisp解释器——erlisp。没有用python,担心性能,所以选择了现学现用lua(实践证明,目前不做任何优化,性能依然完全没有)。
代码
https://github.com/andytt/erlisp
功能
- 作为动态语言,提供了命令行交互和脚本执行两种运行方式。现在在写lua和C/C++的接口。(这是一个运行在虚拟机上的伪虚拟机)
- 变量类型:number、string、list、boolean、function。list其实就是lua的table,去掉了hash表部分,只保留数组部分。
- 语法上对 lisp的cda、cdr进行了模拟...提供了’作为quote的语法糖
- 对于转义字符全部用%实现了,比如%n%t%a等
- 作用域:可定义全局globe或者局部变量local,lua对此非常好实现。
- if条件分支、for遍历列表、while循环:是的,由于lua对递归次数有限制,我们不能够像普通的函数式语言那样用递归来代替循环,因此提供了面向过程的范式
- 函数的定义、调用,由于是函数式语言,所以函数可以作为函数参数,可以被函数返回,是第一类变量
- 对lua5.3中的几个标准库:math、os、io、table、string 进行了封装,部分函数进行了修改。因此可以进行数学运算、时间操作、文件文件夹操作、输入输出及其重定向、列表的删增减改、字符串的查找删除正则表达式等。
- 提供了一个小小的标准库,定义了一些个人觉得常用的操作。
- 实现了python的高阶函数:map、filter、reduce、sort、偏函数等。将函数作为参数传入
- 模块扩展:你可以支持动态的导入.lisp文件,意味着可以按照模块的方法来组织程序。
- 可以像C/C++支持lua那样,利用lua甚至C/C++来为lisp提供库。
- 可以有注释
EXAMPLE
几个例子:
-
函数式,利用函数构造并返回函数: 见b.lisp
-
普通的程序:筛选法求十万内的所有素数并把结果保存到文件中: 见a.lisp
运行需要2.4s左右...性能上来说爆炸了... lua同样代码0.01s python 0.03s 优化的c 仅仅需要0.005s。
-
交互式界面 定义斐波拉起函数在c.lisp中,被其他文件导入并使用
-
命令行交互 见图片
缺点:
- 性能不佳!诸如尾递归之类的地方没优化、本身运行在虚拟机之上……
- lua定义的标准库函数与用户定义的lambda函数在本质上有区别...lua的函数无法完全函数化,可以封装解决...(下面来实现)
- 对所有变量地址均保存在表中,没有安全检查
- 没有提供调试功能、异常处理和并发的功能...导致了无法现代化的使用
- 各种命名不规范...接口不清晰...第一次使用lua用法不地道(即便是python也无法做到pythonic)
- 内存管理?栈?垃圾清理?不存在的...就用lua提供的吧...太tm难了
- 字符串中不能够使用”字符,只能用单引号(在之前写了一半的c语言版本中没这个问题)
- 单引号作为quote语法糖只能用于列表中...函数作为参数传递的时候,必须要加双引号或者(quote xxx)
总结
算是一次小的尝试吧,从词法分析到到语法分析、从定义域的实现到函数的实现,对程序语言的编译运行的过程有了新的理解和体会,算是一点收获吧。
这两天先学的lua语法,大体上与python等动态语言类似,还要继续消化吸收。erlisp的细节还需要处理的更加完善和优化,算是我自己的一个小玩具了吧!!
(甚至想用C重构,作为科大狗的我怕是疯了惹 23333)