Slisp:简单的Lisp编译器(Linux/amd64)
该代码库包含slisp,这是一个编译器,它将读取Lisp程序作为输入,并为Linux/AMD64生成独立的汇编表示。该项目的名称来源于“简单Lisp”或“Steve的Lisp”,你可以任选一个。Lisp传统上是交互性的,并提供REPL,但拥有已编译的版本仍然很有用,并且仍然允许大多数常见的Lisp程序执行。快速链接:INTRODUCTION.md - 功能的简要概述。PRIMITIVES.md - 所有可用函数和特殊形式的详细列表。示例;; 阶乘。哇。(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));;退出代码-如果你更喜欢0,请使用"(exit 3)")在我们的test/目录下有多个示例,包括:factorial.lisp、fibonacci.lisp、fizzbuzz.lisp,example.lisp还有其他杂项代码,最后brainfuck.lisp包含一个有用/有效的brainfuck解释器。需要注意的是,除非在命令行中添加-stdlib=false,否则我们会在所有用户程序之前添加一个标准库的函数。该库本身是一个有用的参考/功能演示:stdlib.slisp - 我们的标准库,用slisp编写。具有良好的打印定义,可以适当地处理已知类型。具有map、length和类似的通用函数。功能:支持绑定、函数、整数、字符串、lambda、列表等。lambda支持闭包。通过int?和cons?等函数进行运行时类型检测。用于堆分配的约定细胞的粗略分配器。数学运算:+、-、*、/和%。比较运算:=、<、<=、>=、>和!以反转结果。特殊形式(cond ..)(defun ..)(do ..)(if ..)(lambda ..)(let ..)(list ..)(set! ..)你可以在PRIMITIVES.md中查看我们所有原语及其详细信息 - 记录了内置特殊形式以及在汇编或slisp本身中实现的标准库部分。反特性:没有垃圾回收。没有宏。添加它们并不是不可能的,但没有quote、quasiquote等,这工作量很大。没有quote 只有在你可以调用eval并且作为编译器时才真的有用?这不是那么容易。用法:构建编译器:go build . 用它编译并链接一个程序:./slisp example.lisp > example.s nasm -f elf64 example.s ld -o example example.o 最后执行你的程序:./example ProTip:当前目录中的任何*.lisp文件将在你运行时编译:make clean all。这样避免了手动重定向、汇编或链接的需要。它还将运行example.lisp文件 - 尽管仅"make clean example"也能做到这一点,以保持整洁。测试:在test/目录下有一些功能测试程序,它们编译固定程序并将输出与已知的良好结果进行比较。你可以通过执行以下命令运行这些测试:cd test && make test 在顶层运行make clean将删除测试工件和编译的程序。除了功能测试,还有golang对内部实现包的测试,这些可以按照标准方式执行:$ 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 还支持golang提供的模糊测试,你可以通过执行以下命令运行五分钟的模糊测试(删除-fuzztime=300s以运行无限期,并删除-parallel=1以同时运行多个实例):$ go test -fuzztime=300s -parallel=1 -fuzz=FuzzProject -v 动机:我花了几周时间编写一个自制语言s-lang的编译器。最初该语言仅使用整数,但后来我添加了浮点数/字符串/指针,并在值的低位标记了类型。我发现处理类型和语法的开销有点复杂,并且有点把自己逼入了墙角 - 我写了一个相当完整的标准库,包含文件I/O、getenv等其他东西。然而,添加更多类型和动态内容感觉会太复杂,因为这将涉及到拆除我所做的很多内容。编译器、标准库和两者之间的接口。因此这个代码库诞生了:实现一个编译器。从基础开始进行适当的类型化。使用宏提高可读性并尽量减少错误的可能性。使用众所周知的SysV ABI,而不是我自己创建的替代方案。使用lisp因为它的语法可以轻松解析。而且我过去写过解释器,所以有一些“龙”,但它们是相对友好的。现在这个编译器比s-lang更“真实”和“可用”,尽管它缺乏质量、标准库、测试用例和s-lang的创造力。我想说,归根结底,两者都
本站免费、广告极少。如果觉得有帮助,可以请我们喝杯咖啡 —— 任何金额都对持续运营有实际帮助。
☕请我喝杯咖啡