这是一个用 uLisp 编写的简单实验性 Lisp 编译器,可将 Lisp 函数编译为 RISC-V 机器码,并可在 Raspberry Pi Pico 2(或其他基于 RP2350 的板)的 RISC-V 核心上运行。
- 介绍:添加执行机器码的功能后,目标是能将 uLisp 函数编译为机器码,此编译器基于之前的项目A Lisp compiler to ARM written in Lisp,由于 Lisp 程序结构一致可被其他 Lisp 程序处理,所以无需编写分词器或解析器,编译器用 uLisp 支持的 Common Lisp 子集编写,可在基于 RP2350 的板的 RISC-V 核心上运行,也可在笔记本或台式电脑上用 Common Lisp 运行并显示生成的代码,但 Common Lisp 没有 uLisp 的defcode命令。灵感来自 Peter Norvig 的书"Paradigms of Artificial Intelligence Programming"。
- 资源:使用编译器需先从RISC-V assembler in uLisp加载 RISC-V 汇编器,完整源代码在Lisp compiler for RISC-V或 GitHub[https://github.com/technoblog...],在 Raspberry Pi Pico 2 上设置 uLisp 见Raspberry Pi RP2350 boards。
- 使用编译器:通过调用compile对 Lisp 函数进行编译,如(compile 'fibonacci),函数将被编译为机器码函数替换原 Lisp 代码,也可通过调用comp显示表达式生成的代码,如(pprint (comp '(* 13 17))),还提供了尾调用优化使递归程序像迭代程序一样高效,并给出了多个简单 Lisp 程序成功编译的示例及 Lisp 和机器码版本的速度比较。
- 规格:理解以下 Lisp 对象:defun、setq、nil、t、car、cdr、算术函数、算术比较、条件语句。
如何工作:
- 寄存器使用:利用栈传递值和存储返回值,规定了 RISC-V 寄存器的使用方式。
- 编译表达式:按步骤生成代码评估每个参数并将结果压入栈,最后一个留在a0,这种基于栈的方式可确保复杂表达式编译正确。
- 递归调用函数:支持函数内部递归调用,将参数和局部变量对应的寄存器存储在栈中。
- 类型:将nil表示为 0,t表示为 1,根据规则为每个编译表达式返回类型::integer 或 :boolean,歧义类型返回 nil。
- 运行示例:用简单示例测试编译器,如因子、Takeuchi 函数、阶乘、Fibonacci 数列、最大公约数、Hofstadter Q 序列、二维递归函数 Q2、组合数 nCr 等,还给出了列表示例,如点积函数,可处理任意长度的向量。
编译器源代码:
- 调用编译器:通过(compile 'fibonacci)等命令编译 Lisp 函数,compile函数判断是否为 Lisp 函数并进行相应处理。
- 主编译器函数:comp函数返回表达式的编译代码,根据不同类型的形式调用相应的处理函数,如 comp-defun 处理函数定义等。
- 实用工具函数:包括生成栈操作指令的 push-regs 和 pop-regs 函数、应用函数到列表并合并结果的 mappend 函数、添加代码类型标签的 type-code 函数等。
- 附录:以简单函数rec为例展示生成的 RISC-V 机器码,展示了 RISC-V Lisp 汇编器利用 16 位压缩指令的情况。引用了相关书籍和基准测试的链接。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用。你还可以使用@来通知其他用户。