Slisp: 简单的Lisp编译器 (Linux/amd64)

Hacker News Top 工具

摘要

Slisp 是一个简单的编译器,它读取 Lisp 程序并生成适用于 Linux/AMD64 的独立汇编表示,支持基本原语、闭包和标准库。

暂无内容
查看原文
查看缓存全文

缓存时间: 2026/06/26 20:20

skx/slisp

来源:https://github.com/skx/slisp

slisp

本仓库包含 slisp,一个编译器,它读取 Lisp 程序作为输入,并生成面向 Linux/AMD64 的独立汇编表示。

该项目的命名源于“简单 Lisp”(Simple Lisp)或“Steve 的 Lisp”,任君选择。

Lisp 传统上是交互式的,并提供 REPL,但拥有编译版本仍然很有用,并且仍然允许大多数常见 Lisp 程序执行。

快速链接:

示例

    ;; 阶乘。耶。
    (defun fact (n)
      (if (<= n 1) 1 (* n (fact (- n 1)))))

    ;; 入口点
    (defun main ()
      (println "显示一些阶乘:")
      (println (fact 4))
      (println (fact 5))
      (println (fact 9))
      (println (fact 10))

      ;; 退出码 - 如果你喜欢,可以用 "(exit 3)"
      0)

test/ 目录下有多个示例,包括:

example.lisp 包含其他杂项代码片段,最后 brainfuck.lisp 包含一个实用/可用的 brainfuck 解释器。

需要注意的是,除非在命令行中添加 -stdlib=false,否则我们会为所有用户程序预置一个标准库函数。该库本身也是功能的一个有用参考/演示:

  • stdlib.slisp —— 我们的标准库,用 slisp 自身编写。
    • 包含一个良好的 print 定义,能适当处理已知类型。
    • 包含 maplength 以及其他通用函数。

特性

  • 支持绑定、函数、整数、字符串、lambda、列表等。
    • lambda 支持闭包。
    • 通过 int?cons? 等函数进行运行时类型检测。
  • 一个粗糙但就绪的 bump 分配器,用于堆分配的 cons 单元。
  • 数学运算:
    • +-*/%
  • 比较运算:
    • =<<=>=>,以及用于反转结果的 !
  • 特殊形式
    • (cond ..)
    • (defun ..)
    • (do ..)
    • (if ..)
    • (lambda ..)
    • (let ..)
    • (list ..)
    • (set! ..)

你可以在 PRIMITIVES.md 中查看我们所有原语的完整列表及其详细说明——包括内置特殊形式,以及标准库中那些用汇编或 slisp 自身实现的部分。

反特性:

  • 无垃圾回收。
  • 无宏。
    • 添加宏并非不可能,但如果没有 quotequasiquote 等,工作量会很大。
  • quote
    • 只有在你能够调用 eval 时才有用,而作为一个编译器?这不容易实现。

用法

构建编译器:

go build .

用它来编译并链接一个程序:

./slisp example.lisp  > example.s
nasm -f elf64 example.s
ld -o example example.o

最后执行你的程序:

./example

专业提示 如果你运行:

make clean all

当前目录下的所有 *.lisp 文件都会被编译。这样就避免了手动重定向、汇编或链接。不过,仅运行 “make clean example” 也会执行 example.lisp 文件,这样更简洁。

测试

test/ 目录下有一些功能测试程序,它们编译固定程序并将其输出与已知正确结果进行比较。你可以通过执行以下命令来运行这些测试:

cd test && make test

在顶层目录运行 make clean 将移除测试产物和编译后的程序。

除了功能测试,还有对内部实现包的 Go 语言测试,这些测试可以以标准方式执行:

$ go test ./...
ok      github.com/skx/slisp	0.004s
ok      github.com/skx/slisp/compiler	0.009s
ok      github.com/skx/slisp/env	(cached)
ok      github.com/skx/slisp/lexer	0.008s
ok      github.com/skx/slisp/parser	0.006s

此外,还支持 Go 提供的模糊测试。你可以通过执行以下命令运行五分钟的模糊测试(删除 -fuzztime=300s 可以无限运行,删除 -parallel=1 可以同时运行多个实例):

$ go test -fuzztime=300s -parallel=1 -fuzz=FuzzProject -v

动机

我花了几周时间为我自制语言 s-lang (https://github.com/skx/s-lang) 编写了一个编译器。最初该语言只使用整数,后来我添加了浮点数/字符串/指针,并在值的低位中使用了适当的类型标记。

我发现处理类型和语法开销有点复杂,并且有点把自己逼入了死角——我编写了一个相当完整的标准库,包含文件 I/O、getenv 和其他功能。

然而,添加更多类型和动态功能感觉过于复杂,因为这将涉及大量重写我之前完成的工作:编译器、标准库以及两者之间的接口。

于是这个仓库诞生了:

  • 实现一个编译器。
  • 从一开始就具有正确的类型系统。使用宏来提高可读性并最大限度地减少出错的可能性。
  • 使用广为人知的 SysV ABI,而不是我自制的替代方案。
  • 使用 Lisp,因为它的语法很容易解析。
    • 我以前曾为其编写过解释器,所以虽有挑战,但相对友好。

这个编译器已经比 s-lang 更“真实”和“可用”,尽管它在质量、标准库、测试用例和创意方面有所欠缺。不过归根结底,两者都是玩具,都是为我的个人学习而存在的。

相似文章

将 Python 转译为 Lisp

Lobsters Hottest

LispE 是 NAVER 推出的一款开源 Lisp 方言,兼具函数式与数组编程特性,并支持 PyTorch、llama.cpp 以及 MLX 等 AI 库。该语言既可作为原生应用运行,也可打包为支持多线程与现代函数式编程特性的 WebAssembly 库。

SLAX脚本语言:XSLT的另一种语法

Hacker News Top

SLAX是XSLT的另一种语法,采用类似C/Perl的语法,以提高可读性和可维护性。libslax开源实现可以解析并执行SLAX文件。

SBCL: 终极汇编代码面包板 (2014)

Hacker News Top

一篇技术博客文章,探讨如何使用SBCL作为汇编代码的面包板,重点介绍基于堆栈的虚拟机技术,如旋转堆栈和高效的原语操作分发,并引用了F18处理器和x87堆栈。

JavaScript 精简

Lobsters Hottest

LispE 是 NAVER 开发的一个紧凑的 Lisp 方言,它结合了函数式和数组语言特性,并支持 PyTorch 和 llama.cpp 等 AI 库。

Vim中的Lisp(2019)

Hacker News Top

详细比较了Slimv和Vlime这两个用于交互式Lisp编程的Vim插件,涵盖安装、功能及推荐。