最近,一个项目吸引了许多开发人员对HN的关注 - 一个创新的开发人员正在尝试使用C语言编写Rust Compiler。开发商说:为了指导Rust的开发,无论价格支付多少,都值得。
原始链接:
作者| John Nunley翻译| Zheng Liyuan
生产| CSDN(ID:CSDNNEWS)
谨慎的生锈爱好者可能已经注意到我最近没有活跃。这种情况有很多原因:我最近经历了一系列坏事,包括亲人的死亡,这使我感到非常惊讶。同时,我承担了更多的工作责任。我不再有很多时间和精力。我为开源项目做出了贡献。也许,我也失去了足以将我献给大学开源世界的热情。
此外,还有另一个原因:我忙于一个占据我大部分业余时间的项目。这个项目是我在开源领域创建的最大项目。如果我可以完成它,那肯定会成为我的峰值。
我正在用纯C语言编写生锈编译器:没有C ++,没有flex或YACC,甚至使用纯C语言。这个项目称为推土机。
(CSDN付费下载自觉中国)
你为什么要这样做?
如果您想了解为什么我踏上了这条“疯狂”道路,则首先需要了解引导(指导方法)及其重要性(So -so all call of call guidance方法,这是编程中的一种常见技术,这意味着要通过现有现有现有的现有技术现有的现有基本代码或资源以构建更复杂的系统或工具)。
假设您用Rust编写了一些代码。为了运行这些代码,您需要先对其进行编译。编译器是一个程序,可以分析您的代码,验证其正确性,然后将其转换为CPU可理解的机器代码。
对于Rust而言,主要编译器是Rustc-即运行货物时,所谓的基础程序。我不得不说Rustc是一个很棒的软件,甚至可以说是开源社区的宝藏。它的代码质量可以与Linux内核和地震III源代码相提并论。
但是,Rustc本身也是一个程序,因此它还需要编译器将其从源代码到机器代码编译。所以问题是:rustc写了哪种语言?
这样,Rustc是一个用Rust编写的程序,它是为了编译Rust Code。但是,请考虑一下,如果Rustc用Rust编写,并且我们需要使用Rustc编译Rust Code,这意味着我们需要使用Rustc来编译Rustc ...?
对于普通用户来说,这实际上很好,因为我们可以从Internet下载Rustc并直接使用它。但是有一个问题:谁编译了第一个Rustc,首先必须有“鸡”才能“鸡蛋”?这从哪里开始?
实际上,此问题并不复杂:每个新的Rustc版本都是由先前版本的Rustc编辑的。换句话说,Rustc 1.80.0版本使用Rustc 1.79.0版本编辑,Rustc 1.79.0版本由Rustc 1.78.0版本编译,等等,可以追溯到Rustc版本0.7。当时,编译器是用OCAML编写的,因此只需要一个OCAML编译器才能获得完整的Rustc程序。
好吧,解决了问题,我们已经弄清楚了如何从头开始创建Rustc。但是,我们仍然需要一个版本的OCAML编译器才能正常工作。那么,OCAML编译器使用了哪种语言?
呃...没关系!一个项目可以通过Guile成功编译OCAML编译器,而Guile是方案的众多变体之一,而方案是LISP的众多变体之一。此外,Guile的口译员是用C写的。
结果,所有这些最终都指向C语言。我们只需要用GCC编译,一切都可以顺利完成。因此,我们只需要编译GCC,而GCC则写在... C ++中?路口
此陈述有点不准确。 GCC用C语言写在第五版之前,并且不乏C编译器在这个世界上写的C编译器……但这仍然没有回答我们的问题。什么是第一个C编译器?编辑语言?那么第一个集会写了什么?
原理简介
这就是我想介绍Bootstrable Builds项目的目的。我认为,这是开源社区中最有趣的项目之一,基本上属于代码炼金术。
Linux引导过程以512个字节二进制种子开始。该种子包含最简单的编译器:它可以接收十六进制的数字并输出相应的原始字节。例如,以下是编译器编译的“源代码”:
31 C0 # xor ax, ax
8E D8 # mov ds, ax
8E C0 # mov es, ax
8E D0 # mov ss, ax
BC 00 77 # mov sp, 0x7700
FC # cld ; clear direction flag
88 16 15 7C # mov [boot_drive], dl
请注意,井背后的所有内容都是笔记,并且所有空白字符都已删除。坦白说,我不确定这是否可以称为编程语言。但是严格来说,这确实是分析和分析源代码。
接下来,该编译器将编译一个非常简单的操作系统,一个不起眼的外壳和一个稍微高级的编译器。该编译器编译了一个更高级的编译器。经过几个步骤后,您的内容与汇编代码类似。
DEFINE cmp_ebx,edx 39D3
DEFINE je 0F84
DEFINE sub_ebx, 81EB
:loop_options
cmp_ebx,edx # Check if we are done
je %loop_options_done # We are done
sub_ebx, %2 # --options
说到哪个,您会觉得我认为汇编代码比其他方面更高,这似乎有些奇怪,对吗?
但这足以获得一个非常基本的C语言子集c语言编程软件教程c语言编程软件教程,然后使用此子集来编译稍微高级的C编译器。经过几步之后,您可以编译TinyCC。然后,您可以指导YACC,基本的Coreutils,Bash,Autotools,并最终达到GCC和Linux。
我说,这可能无法完全反映这一过程的魅力,但这确实令人着迷。简而言之,从“二进制文件足以手动分析”,逐步到Linux,GCC以及其他所有内容,您基本上都经历了它。但是,让我们再次从TinyCC开始。
目前,生锈在此过程中显得很晚。他们使用mrustc,这是一种用C ++替代的锈蚀,可以编译Rustc 1.56版本。在此基础上,他们编译了现代的生锈代码。
这里的主要问题是,当引入C ++时,指导过程基本结束了。因此,如果您想在引入C ++之前任何时候使用Rust,那是不可能的。
因此,对我来说,如果可以从C中引导生锈的编译器,那将是很棒的。具体来说,它是一个可以由Tinycc指导的生锈编译器。同时,假设它在系统中没有用,则该编译器为推土机。
未来计划
在过去的两个月中,我一直在忙于推土机项目:我必须有差的空闲时间来写一种我讨厌的语言。
该项目不使用任何扩展功能。目前,TinyCC和CPROC可以成功编译。我将QBE用作后端。此外,我认为系统上没有其他工具,只有一个C编译器和一些非常基本的外壳实现,没有其他工具。
在本文中,我不会探讨编写编译器的原始体验。但是到目前为止,我已经完成了词汇分析设备和语法解析器的相当一部分。我将被延迟为宏/模块扩展名。类型检查当前仅支持i32,而代码生成仍然有些粗糙 - 但这已经是一个不错的开始。
目前,我可以成功编译以下代码:
fn rust_main() -> i32 {
(2 - 1) * 6 + 3
}
那么,下一步该怎么办?这是我的计划:
(1)缓慢推进推土机,直到可以使用libc编译一些基本的示例代码,然后编译Libcore,最后转到Rustc。 (顺便说一句,我计划编译Rustc的Cranelift后端。这部分完全用Rust编写。由于我们假设没有C ++,所以我们无法编译LLVM。)
(2)创建相当于货物的工具,您可以使用推土机来编译Rust包装。
(3)在Rustc中找出自动代码源文件并将其删除。根据BootStrable项目的规则,不允许自动生成代码。
(4)创建一个可以用于编译Rustc和货物的过程,然后使用我们编译的Rustc/Cargo版本重新计算Rustc/Cargo的标准版本。
毫无疑问,这是我到目前为止创建的最困难的项目,我也怀疑我是否可以完成它。但是你知道吗?它失败了,但失败了,总比从未尝试过好。