Raku Other Impl
— 焉知非鱼Raku Other Impl
(这是同一作者的法语文章 Raku en 2020 的翻译/改进版。)
感谢 Elizabeth Mattijsen 帮助校对和提供建议。
Table Of Contents #
- Birth
- Renaming process from Perl 6 to Raku
- Implementations based on Parrot
- Implementations based on Pugs
- Other implementations
- Conclusion
Raku 的历史
Raku 解释器和虚拟机的历史真的不简单…如果你听说过 “Parrot”、“PIR”、“PASM”、“Pugs”、“Rakudo”、“MoarVM”、“NQP”、“Rakudo on JVM”、“Rakudo on Parrot”、“Mildew”、“Ponie”,但你对所有这些实现感到困惑,那么这篇博文就是为你准备的。
我做了一些研究,以澄清所有的历史和技术细节,并将所有的结果收集在这里,加上几个自制的原始草图,使其对你来说非常清晰。
Raku 的诞生 #
Raku 诞生于 2000年7月18日,源于一个著名的事件:约翰-欧文特在一次会议上把咖啡杯扔到墙上。
改名字的过程: Perl 6 → Raku #
一种改变其名称的编程语言…这并不经常发生!"。
最近,Raku 庆祝了它的第二年(或21年)。以下是改名过程。
- 很久以前(大约 2005 年),人们讨论过一个别名,但后来不了了之。
- 在回答一个问题时,Larry Wall 提出了一个别名
- Perl 6 社区的一些人要求使用这个别名
- 并由 Larry 验证
- 后来,核心团队的一个成员(Elizabeth Mattijsen)在 Raku 的官方 GitHub 上开了一个"问题",要求改名。
- 然后,Elizabeth 向 Raku 的 Git 官方仓库提出了一个合并请求(要求维护者投票)。
- 人们投票支持(或弃权),然后是 Larry Wall 的"祝福"。
- 改名完毕,请欢迎 Raku!
下面是改名过程中的有关链接:
- August 2017: Original idea for Perl 6 Alias
- October 2018: A request to Larry Wall for an alias
- November 2018: On Raku
- August 2019: Liz issue — Perl in the name is confusing
- August 2019: Liz PR — Path to Raku
- September 2019: On renaming Perl 6
- October 2019: Blessing of Larry then renaming
编译器、框架和虚拟机
在这第二部分中,我将详细介绍 Raku 语言过去的实现情况。准备好了,首字母缩写词就要来了!
哪种是"官方"实现? #
简短的回答。Rakudo 和 MoarVM。
(关于 Rakudo/MoarVM 的细节在本系列的前一篇博文中)
最初的决定是,没有任何实现会被定义为 Raku 的"官方"实现,而是说 “Raku 是通过官方测试套件的东西”。事实上,自2012年以来,有一个事实上的官方实现,即 Rakudo + MoarVM。
在此之前,有 Parrot 框架(2002-2012)以及 Pugs(2005-2007)和其他各种编译器和运行时环境(Mildew、Niecza、Yapsi…)。这个技术和历史部分将在本文的最后讨论。但让我们回过头来谈一谈开始。
最早宣布创建 Raku 的时间可以追溯到 2000年7月19日。Larry Wall 的想法是使其成为一个超社区项目,直到语言设计,所以他将从要求对规范做出贡献开始。这导致了 361 个 RFC,Larry Wall 从中产生了启示录,然后由 Damian Conway 在诠释中解释,后来又在提要中进一步详细说明。
为历史学家或好奇心强的人提供的链接:
- 2000-1018: the Raku museum repository partially saves “events” that are part of Raku’s history
- 2000: Old blog post criticizing the RFC process (early)
- 2005: Get involved in Pugs
- 2006: Get involved in Perl6
- 2008: Get involved in Perl6
- 2009: Get involved in Perl6
- 2010: Happy 10th anniversary Perl 6 (必读 ⚠️)
- 2015: Flavio Glock interview
Parrot
创建于 2002 年,该框架和 [Parrot 虚拟机](http://docs.parrot.org/parrot / latest / html)长期以来一直是 Raku 实现的核心(今天已经不是这样了)。Parrot 诞生于一个愚人节,宣布 Perl 和 Python 的统一,甚至即将发行一本关于这个主题的书。
为什么要建立一个新的虚拟机?
2001 年对 JVM 进行了研究,但认为它不适合动态语言(2010 年仍然不适合,更别提 2021 年了)
编译 #
Parrot 提供的不仅仅是一个虚拟机,Parrot 是一个语言创建、编译和执行框架。这个框架使建立高级语言(HLL)成为可能,而且很容易和快速。它已经被 Rakudo 实践了很长时间。
PCT #
PCT 是 Parrot Compiler Tools 的缩写。它的目的是能够创建一个编译器和一个高级语言执行环境(HLL)。
PCT 是用 PIR 写的 (请看下面的汇编部分).
PAST #
PAST 是 Parrot Abstract Syntax Tree 的缩写:语法树的内部表示法。
HLL #
HLL 是 High Level Language 的缩写。
PGE #
PGE 原名为 P6GE,PGE 是 Perl Grammar Engine 的缩写。以 HLLCompiler 为基础。一个 PGE 规则看起来像这样。
rule term { <number> | \( <expr> \) }
rule number { \d+ }
rule expr { <term> ( '+' <term> )* }
PGE 被另一个 Raku 编译器 Pugs 所使用(见下文)。
TGE #
TGE 是 Tree Grammar Engine 的缩写。
PACT #
PACT 是 Parrot Alternate Compiler Toolkit 的缩写。 PACT 是 PCT 的替代方案,因为 PCT 被认为太有限。
汇编 #
PASM #
PASM 是 Parrot assembly language (PASM) 的缩写。低级别的代码已准备好由 Parrot VM 转换和执行。PASM 代码看起来像这样。
set I1, 1
REDO:
gt I1, 10, END
print I1
print " "
inc I1
branch REDO
END:
print "\n"
end
参考:
- PASM code examples
- LinuxMag articles from french mongueurs on Parrot assembler writing: 1, [2](http://articles.mongueurs.net/ magazines / linuxmag98.html)and 3.
IMCC #
IMCC 是 Intermediate Code Compiler 的缩写。 它是一个创建和运行 Parrot 字节码的替代工具
IMCC 带来了自己的语言,通常被称为 Parrot 中间语言(PIR)。IMCC 嵌入了 Parrot 的运行环境,因此 IMCC 可以从 PIR 编译到 PASM,然后从 PASM 编译到 PBC,然后执行这个字节码。IMCC 还可以进行优化,尽管它默认不进行优化。
PIR #
PIR 最初被称为 IMC,它是 PASM 的一种叠加,而不是一种高级语言。包含 PIR 代码的文件的后缀为 “.imc”
这就是 PIR 的样子。
.sub loopy
.local int counter
counter = 0
LOOP: if counter > 10 goto DONE
print counter
print " "
inc counter
goto LOOP
DONE:
print "\n"
end
.end
你可以从这个 IMCC 介绍或这篇关于如何编写 PIR 的文章中了解更多。请看这里的 PIR 例子或甚至 [FR mongueurs 关于 PIR 的详细文档](http://articles.mongueurs.net/magazines/linuxmag122 .html)。
Execution #
NCI #
NCI 是 Native Call Interface 的缩写。
PMC #
PMC 是 PolyMorphic Container 或 Parrot Magic Cookies (在虚拟机中表示数据的方式) 的缩写。
PBC #
PBC 是 Parrot Byte Code 的缩写。
Parrot 虚拟机 #
Parrot 虚拟机是一个基于注册表的虚拟机,它不是"标准"(如JVM)。
以下是 Parrot 虚拟机的一些特点。
- 能够管理静态和动态语言
- 写时复制
- 管理连续性和封闭性
- 可以嵌入到 C 代码中
- 多态容器(灵活的类型存储)
很容易将 Parrot 包含在 C 代码中或在 Parrot 中调用 C([原生调用接口](http://docs.parrot.org/parrot/latest/html/docs/pdds/draft/pdd16_native_call .pod.html))。
基于 Parrot 的 Raku 实现(2002-2012) #
或者用一个合并的 IMCC 和 Parrot 阶段(后来因为 IMCC 包含 Parrot)。
许多细节可在 Parrot 设计文档中找到。
Parrot 的问题 #
如果说 Parrot 最初处于 Raku 的中心,那么随着时间的推移,这种情况已经发生了变化。
- 2008: “虽然 Parrot 是长期部署 Perl 6 的最可靠的解决方案,但另一方面,事实证明 Parrot 所接受的挑战比之前预期的要消耗更多的时间和资源。” (Perl 基金会新闻)
- 2013: “最新的消息是,Parrot 虚拟机不再是唯一一个享受 Rakudo 独家服务的人了。” ([关于 Perl 6 的一切](http://www.josetteorama.com/all-about-perl-6 -interview-of-jonathan-worthington-part-1-of-3 /))
- 沟通问题
- Parrot 逐渐远离了Perl 6(通过变得更加通用)。
渐渐地,Rakudo 编译器已经从 Parrot 中解放出来,现在正瞄准新的虚拟机。
Pugs (2005-2007)
从这里我们开始考古,真正的考古。
在他短暂的存在中,Pugs 探索了许多架构选择。Pugs 指的是解释器、编译器、运行时环境和测试套件。编译器可以编译成 Haskell、JavaScript、Perl 5 或 PIR(代表 Parrot,如果你记得的话)。
Pugs 是用 Haskell 编写的,在 2007 年后陷入了休眠状态。
编译 #
下面是围绕 Pugs 实现构建的概念。
PCR #
PCR 是 Pugs Compiler Rules 的缩写。这是 Raku 的正则表达式引擎的 Perl 5 实现。PCR 在 Pugs 中取代了 PGE。
LREP #
LREP 演变成 Pugs::Compiler,后来又演变成 MiniPerl6。
Pugs::Compiler #
Pugs::Compiler 是一套用于编译 Raku 的 Perl 5 模块。
MiniPerl6 #
曾是 Pugs 的一部分,但在一个单独的目录中。MiniPerl6 变成了 KindaPerl6,然后是 Perlito6。
KindaPerl6 #
KindaPerl6 或 KP6 是一个 Raku grammar 的 Raku 实现,在 Perl 5 中具有引导功能。KindaPerl6 是由 MiniPerl6 构建的。
Execution #
PIL #
PIL 是 Pugs Intermediate Language 的缩写。PIL 不是人类可读的格式,而是 Pugs 内部的一个抽象的语法树。
PIL-Run #
PIL-Run 是建立在一组读取和运行 PIL 的 Perl 5 模块之上的。PIL-Run 是 Pugs 在 Perl 5 中的后端…在开始时。
基于 Pugs 的实现 #
Pugs + 各种后端 #
“Pugs compiles for Parrot (PIR)”
“Pugs compiles (transpiles?) To JavaScript”
“Perl compiles (transpiles?) To Perl 5”
v6 #
v6-pugs 然后是 v6-alpha 和现在的 v6.pm) 是对 Pugs 的完全重写,使用了 Raku(Pugs::Compiler 和相关模块)和 Perl 5 的混合。它重用了 PIL-Run 的运行环境和"CPAN 的一半"的代码:grining。
现在 v6 在 Perlito6 中发布。v6.pm 是 Perlito 和 Pugs 在 Perl 5 中的前端。
Perlito #
Perlito 项目是由 Flavio S. Glock 领导的。Perlito 项目实际上包含了多种语言的多个编译器,针对各种后端。
- 将 Perl 5 编译成 Java 源代码
- 在 JVM 中直接运行 Perl 5
- 将 Perl 5 编译成 JavaScript 源代码,直接在浏览器或 Node.js 中运行 Perl 5
- 将 Raku 编译为 JavaScript 源代码,直接在浏览器或 Node.js 中运行 Perl6
- 从 Perl 5 编译到 Perl 5
- 从 Raku 编译到 Perl 5
- 从 Raku 编译到 Python 2.6
- 从 Perl 5 编译到 Perl 6 (正在进行中)
- 从 Raku 编译到 Ruby 1.9 (正在进行中)
- 从 Raku 编译到 Go (正在进行中)
- 从 Raku 编译到 Common Lisp (SBCL) (正在进行中)
他不能做的一件事是把 Perl 5 翻译成 Raku。
MiniPerl6 和 KindaPerl6 组成了 Perlito6。Perlito5 是 Perlito6 到 Perl 5 的一个移植。它是 “用 Perl 5 实现的 Perl 5”。Perlito5 本身是用 Perl 写的。另一方面,Perlito6 是用 Raku 编写的。
Perlito 只实现了 Raku 的一个子集,称为"有用的子集",它:
- 没有列表上下文
- 没有继承
- 没有 laziness
- 有闭包,但没有协程或连续过程
- 没有 multis
这个"有用的子集"有点类似于 NQP(关于 NQP 的细节,请看之前的博文)。
其它编译器、运行时环境和虚拟机
在这一部分,我将继续我对围绕编译器、运行时环境和传统虚拟机的倡议的巡视。
STD 和 viv #
STD 和 viv 是 Larry Wall 的作品。
我们在 STD 中发现了 Raku 的 grammar…用 Raku 写的(当时还没有编译器!)。😏 这是引导问题的开始 😀
VIV 或字面上的罗马数字 “VI → V”(因此是 “6到5”)是一个能够从 Perl 6 转换到 Perl 5 的模块。
SMOP #
最初称为 YAP6,SMOP 代表简单元对象编程
SMOP 是用 C 语言为 Raku 编写的编译器和运行时环境,但我们有时说 SMOP 只指运行时环境(它可能是其他编译器的目标)。
SMOP 不是一个虚拟机,而是一个类似于 Perl 5 的运行环境,同时具有管理 Raku 的功能。
Mildew #
Mildew 是一个 STD 到 SMOP 的编译器。
它直接使用了 STD grammar。
Elf #
Elf 是一个用 Raku 编写的编译器,具有 Ruby 语法。它可以发行 Perl 5 或 Lisp。它从未完成。人们期望 Elf 能够针对 SMOP。
Ponie #
Ponie 是 Perl On a New Internal Engine 的缩写。这涉及到在 Parrot 虚拟机中运行 Perl 5。在 2006 年停止了。
Punie #
Punie(直接引用了 Ponie)是 Parrot 的一个 Perl 1 编译器。
Yapsi #
Yapsi 是 Yet Another Perl Six Implementation 的缩写。它是对编译器及其 Raku 运行环境和 Raku 虚拟机的实现。
SIC means (S??) Instruction Code, 这是 Yapsi 自己的字节码。
Niecza #
Niecza 是一个用 C# 编写的针对 CLR(Mono)的 Raku 编译器。
Topaz #
Topaz 是在 Perl 6 之前开始用 C++ 重写 Perl 5 的核心,最后放弃了。
Sapphire #
Sapphire是 2000年9月对 Perl 5 内部结构的另一次重写,在 Perl 6 公布后不久。更多的是实验,而不是其他的东西。
吁!这是最后一个了。我们完成了。 😀
结论
在 Raku 以及它的历史和它的实现的历史中可以找到许多有趣的概念(尽管它们中的大多数都已经是消失的世界的一部分了,但它们很值得我们仔细研究)。
我希望这篇冗长的博文能够拨开 Raku 实现的曲折迷雾,了解它的历史,并突出该语言的概念。