Evocation - 从宇宙中召唤计算的青蓝火焰,将其能量编织成织物,使我们能与之交融。
摘要
Evocation 是一种 Forth 方言和自托管编译器,针对 amd64 架构,专为语言设计实验而设计,并具有自举特性以生成可审计的二进制文件。
<p><a href="https://lobste.rs/s/kpegs1/evocation_call_forth_blue_green_flame">评论</a></p>
查看缓存全文
缓存时间: 2026/09/21 22:29
# README.txt - evocation(召唤)
从宇宙中唤起计算的蓝绿火焰,将其能量编织成织物,让我们得以与其共享血脉。
来源:https://code.irenes.space/evocation/tree/README.txt
```
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401
```
```
. ~ . ~ ~~ . ~~ ~~~ ~ ~~~ ~~~~ ~ ~~~~~~~ ~~~~~ ~~~~~~~~~~~~~~
. ~~ 召唤! ~~ ~~~~~~~~~~~~~~~
或者,如何召唤蓝绿火焰 ~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~
```
**Evocation** 是一种基于 Forth 的方言,根据 Irenes 的偏好发展而来。它的目标是未来成为一个平台,用于实验解析理论、类型理论、数据库,以及其他 Forth 传统上不擅长的领域,同时它本身也是一个语言设计实验品。它是一个自托管的编译器,这意味着构建它所需的唯一材料就是它自身的一份拷贝。它的编写完全不依赖可微神经网络,未来也永远不会。Evocation 具有实用价值,但创造它的首要原因是精神和美学上的:Irenes 相信它是一个理应存在的事物,并选择以他们能找到的最愉快的方式创造它。
目前,Evocation 仅针对 amd64 架构。作为编译型 Forth,它针对 64 位架构是相当少见的。除了自托管,Evocation 也是自举的,这意味着编译器可以在一个特殊的“展示过程”模式下运行,该模式不会输出常规的二进制文件,而是输出一个带有大量注释的十六进制转储,详细解释了每个输出字节的来源以及如何审计其正确性。这个十六进制转储适合签入源代码管理,然后可以通过一个本身易于审计的过程转换为可执行的二进制文件。
这个十六进制转储策略基于来自 mescc 和 guix 开发者的洞察:源代码与二进制文件的区别在于注释。然而,在 Irenes 所知范围内,Evocation 是第一个能够从高级语言实现(而非汇编语言)生成自身十六进制转储的编译器。因此创造了“自举”这个术语来描述它。
不熟悉 Ken Thompson 关于此主题的经典论文 [1] 的读者,会发现这是一篇简短、轻松的读物,为这类自举提供了动机。关于如何使用自举的细节将在下面的“为分发而十六进制化 Evocation”部分描述。
本文档是一个持续进行的工作,但正在接近成为一个可行的介绍。请务必对那些你希望它谈到但尚未涉及的内容提出意见。
如果你是通过非链接方式获得此代码仓库的,其权威副本位于 https://code.irenes.space/evocation,但无需联网;你需要的一切应该已经在这个目录中。
~~~~~~~~~~~~
~~ 构建 ~~
~~~~~~~~~~~~
由于我们选择不以二进制形式分发 Evocation,你目前还没有它的副本,也无法在首次构建时利用其自托管特性。幸运的是,因为它也是自举的,你无需这样做。只需运行:
```
$ ./hex < evoke.hex > evoke
$ chmod 755 evoke
```
这些是 Unix shell 命令,需要在某种命令终端中运行。如果你运行的是 Linux 或其他 Unix 变体,你可能已经有了提供终端的程序;有很多选择。在其他操作系统上,你可能需要去找一个。使用终端一开始可能很吓人,但一旦熟悉,它就是一个非常强大的创造性工具,会改变你与计算机的关系。我们保证不会过快要求过高的熟练度。
如果你需要了解终端,你可能会喜欢《腐女的 Web 开发指南》[2] 或 Wizard Zines [3]。
这个名为 "hex" 的小程序已作为二进制文件签入 git,是 Evocation 所有操作的信任根基。它是唯一的二进制组件。如果你愿意,你可以通过任何你希望的方式检查其内容,并与 "hex" 本身的自举十六进制转储(位于文件 "hex.hex" 中)进行比较,该文件描述了每个字节的目的和来源。它很短。
这是一个显著更大的工程,但如果你有充分的理由,你可以用同样的方式审计 "evoke.hex" 的内容。
现在,将你的 "evoke" 二进制文件保存在安全的地方,并在你修改 Evocation 时用它来构建新版本。
~~~~~~~~~~~~~
~~ 探索 ~~
~~~~~~~~~~~~~
你现在可以尝试 Evocation 了。与它交互式输入:
```
$ ./evoke
." Hi, Irenes!"
6 7 * . newline bye
```
看看它打印了什么!
**(待办:给出逆波兰表示法用于算术的示例)**
一些开始时有用的词包括 `list-dictionary` 和 `describe`。
**(待办:展示如何使用它们)**
字符串字面量的语法是 `s" ..."`。这里发生了一些非常微妙的事情:它是小写字母 "s",一个双引号,然后是一个空格。然后你输入字符串的实际内容,最后再输入另一个双引号。
上面示例中的单词 "Hi, Irenes!" 属于一种密切相关的语法,它使用句点代替字母 s,并将字符串打印到你的终端,而不是返回它。
无论你使用 `s"` 还是 `."`,引号后的空格都是强制性的。如果你更熟悉除 Forth 之外的几乎所有语言,这可能看起来很奇怪,但这是 Forth 的常见惯用法。要求空格允许字符串字面量像任何其他以空格分隔的单词一样被词法分析。
与大多数语言不同,这里没有特殊的“运算符”或“标点字符”概念可以“中断”另一个单词或紧挨着另一个单词的开头。所有内容都由空格分隔。当然,在现代 Forth 方言中,为此类事物添加特殊的词法分析功能也很常见。Evocation 不这样做,因为最终复杂的语法和文法将在更高层实现,使用尚未存在的实验性解析形式体系。
如果你想看看如果以更简单的方式实现此特性会在哪里,你可以阅读名为 `word` 的单词的定义,在 interpret.e 中。
如果你去看了并且在想:是的,Evocation 的词法分析器就是这么短和简单。它能够如此简单的原因之一是像 `s"` 这样引入特殊语法的单词会自己对之后的内容进行词法分析。
**(待办:展示如何定义单词)**
Evocation 有高级流程控制词:`if`, `unless`, `if-else`, `forever` 和 `while`。高级流程控制是现代 Forth 方言常见的添加,但每个方言的做法都略有不同。Evocation 的流程控制词是后缀操作,并与花括号一起使用,像这样:
```
$ ./evoke
: count 10 0 { 2dup < } { space dup . 1+ } while 2drop newline ;
count
```
它会打印什么? :)
Evocation 的高级流程控制仅在编译代码中有效;此示例定义并编译了一个名为 "count" 的新词,以展示其功能。如果你尝试在单词定义之外使用 `{ ... } { ... } while` 语法,它将不会如你所愿地工作。这是因为,与一些现代 Forth 不同,Evocation 没有通用的内存管理设施;它使用一种称为日志(log)的东西,这使得分配内存容易,但释放内存困难。为了循环通过一个代码块,它必须被分配在某处。因此,设计上注意不鼓励会消耗大量内存空间的编程习惯。
~~~~~~~~~~~~~~~~~~~~~
~~ 高级特性 ~~
~~~~~~~~~~~~~~~~~~~~~
**(待办:这部分应该放在哪里?是否应该有一个交互式教程?)**
```
: baz ." baz baz baz!" newline 1 nexit ;
: bar ." bar start" newline baz baz baz ." bar end" newline ;
: foo ." foo start" newline bar ." foo end" newline ;
foo
foo start
bar start
baz baz baz!
baz baz baz!
baz baz baz!
bar end
foo end
```
```
: baz ." baz baz baz!" newline 2 nexit ;
: bar ." bar start" newline baz baz baz ." bar end" newline ;
: foo ." foo start" newline bar ." foo end" newline ;
foo
foo start
bar start
baz baz baz!
```
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~ 阅读 Evocation 的源代码 ~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
即使你只是对使用 Evocation 感兴趣,而不是修改它,我们也鼓励你至少浏览一下源代码。如果你看过,即使只是一点点,下次就不会那么害怕了。它的注释非常丰富,旨在让任何有一点编程知识的人都能阅读,即使你以前从未做过系统编程。如果你发现其中有什么困惑,请不要害怕提问!很可能其他人也很困惑,分享你的问题有助于改进文档,并让其他人通过观察学习。
负责编译 Evocation 本身的顶层源文件是 evoke.e。它真的很短,值得现在快速浏览一下。它列出了所有其他源文件、它们被加载的顺序以及它们如何被处理。
让 Evocation 能够运行的文件是 execution.e 和 core.e。值得慢慢阅读它们。在你读完 core.e 之后,你将知道许多可以在 Evocation 内部作为命令使用的基本词。
Evocation 的大部分内容是用它自己的汇编语言版本编写的。文件 amd64.e 实现了所有汇编指令。用汇编语言编写真正的程序还需要解析标签(label),这是一种给地址命名的特殊语法。标签的行为全部在 labels.e 中实现。
在汇编语言方面,还有 linux.e,它包含了用于执行特定于 Linux 操作系统(如读取输入)的操作的汇编词;以及 elf.e,它包含了用于输出特殊文件头(让操作系统理解该文件是可执行程序)的词。
在 Forth 相关的部分,input.e 和 output.e 负责将文本输入和输出语言。定义单词的基础设施在 dynamic.e 中,其语法在 interpret.e 中。高级流程控制词在 flow-control.e 中。execution.e 的一些功能不得不单独分到它们自己的文件中,因为编译器工作的细节;那些东西在 execution-suport.e 中。
所以,在那些相对正常的编译器内部组件文件中,所有这些都相当自成体系……然后还有转换设施(transformation facility)。这是 Evocation 最独特的架构决策,位于 transform.e 中。它的文档完善,但也极其概念密集。尽管可以浏览一下,这是建立对这些事物的熟悉感的唯一途径,但在你对理解转换设施抱有高期望之前,你可能应该对其他内部组件有扎实的理解。没关系,你可以在理解它之前就从中受益:转换提供了将 Forth 代码编译成独立可执行文件的核心技巧。在 evoke.e 中对 label-transform 的调用,以及在 execution.e 中对 log-load-transform 的调用,是编译被移交给转换设施的两个位置,你可以基本上认为它是有效的,直到你感觉准备好。
如果你想看比 Evocation 本身更小的程序示例,quine.e 是一个用正宗 Evocation 编写的小程序,它输出自己的源代码;hello.e 是用 Evocation 汇编编写的 "hello-world";而 hex.e 是另一个用 Evocation 汇编编写的较小程序,可能是一个很好的示例,展示如何用这种方式做稍微复杂的事情。所有这三个都是自包含的,仅由那个文件加上对 Evocation 内置库的调用组成。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~ 修改 Evocation 的内部结构 ~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
在你的探索过程中,可能会有一个时刻你想要对编译器进行更改。当你有一个想尝试的更改时,你可以使用现有的 Evocation 副本来编译一个新的,像这样:
```
$ (cat labels.e elf.e transform.e execution.e; echo 's" pyrzqxgl" allocate-string dup 262144 read-to-buffer'; cat core.e linux.e output.e amd64.e execution-support.e log-load.e; echo pyrzqxgl swap 262144 read-to-buffer; cat core.e linux.e output.e amd64.e execution-support.e log-load.e dynamic.e input.e interpret.e flow-control.e linux-dynamic.e ; echo pyrzqxgl; cat evoke.e) | ./evoke > evoke2
$ chmod 755 evoke2
```
然后你可以运行 ./evoke2 并尝试你添加的新功能。很有趣,对吧? :)
如果你计划提交你的更改以供纳入,请同时验证你的编译输出是否稳定:再次运行编译命令,但将最后一部分从 "./evoke > evoke2" 更改为 "./evoke2 > evoke3"。evoke2 和 evoke3 两个版本应该逐字节相同;如果不是,请修复它。这是一个重要的属性,如果我们失去它,将很难恢复,更容易在当下维护它。
关于学习操作系统内部结构和发现更多参考资料,Irenes 推荐 osdev wiki [4]。特别是,Evocation 的可执行文件格式是 ELF [5] 的 64 位版本 [6];它与内核的接口是 System V ABI [7] 的 AMD64 版本 [8];并大量参考了 Intel 处理器参考手册 [9] 来理解指令集架构。
如果你想了解更多关于 Forth 实现的具体内容,请查看 Jonesforth [10]。如果你想看看现代 Forth 方言在不同创意方向上的发展,请看 Factor [11]。如果你对 Forth 之外的连接式语言感兴趣,请查看 uxn 虚拟机 [12] 及其语言 uxntal [13]。
Irenes 遗憾地没有关于学习编译器概念的建议。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~ 为分发而十六进制化 Evocation ~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Evocation 二进制自举的长期策略尚未准备就绪,但仍然在这里描述,因为这应该是最终解释的位置,并且在创建各个部分时更容易记录。二进制自举策略基于所谓的“十六进制转换”(hex transform),这是 Evocation 转换设施(位于 transform.e 中)提供的最复杂的转换。十六进制转换的任务是将整个编译过程(原本会生成一个可执行二进制文件)进行转换,并取而代之输出该二进制文件的带注释十六进制转储,描述其...
相似文章
EvilVM:Forth Shellcode
EvilVM 是一个原生代码的 Forth 编译器,作为位置无关的 shellcode 部署,用于信息安全环境中的远程代码执行,提供交互式 shell 以及远程代码传输和编译功能。
AsmEvo: 带功能等价验证的AMD GPU内核智能汇编级优化
AsmEvo 是一个用于AMD GPU内核的智能汇编级优化器,通过提出低级编辑并验证与原始二进制文件的功能等价性来提高性能,在MI308X GPU上实现了高达3.88倍的加速。
EvoMap/evolver
Evolver 是一个由 GEP 驱动的 AI 代理自演化引擎,可自动化提示词优化并创建可审计、可复用的演化资产。该项目正从完全开源过渡到源代码可用,同时保持与现有 MIT 和 GPL-3.0 版本的向后兼容性。
持久递归世界实现自主软件演化
介绍了 EvoX Genesis,一个围绕持久项目而非持久代理组织长周期软件开发的框架,以低成本和高性能自主构建了基于 Rust 的 C 编译器,并重新实现了 MESA 数值模块。
Révo编程语言
Revo 是一种编程语言,具有清晰的数据流、错误即值、编译时执行和基于纤程的并发特性。它使用Zig构建,并提供可选类型和强推断功能。