我读到了关于bootstrapping但是还没有完成它。 我想解释一下我是如何看待它的,你要指出它是不是真的。 为了创建一个自编译它的编译器,它应该遵循以下步骤:
让我们有X和Y编程语言。
我觉得我的解释是缺乏重要的细节 如果有人能像我试图做的那样解释数学符号,我会很高兴。
答案 0 :(得分:0)
在大多数情况下,您的步骤似乎是正确的,除非您似乎在混淆源语言和目标语言。我不确定这些只是错别字还是你真的很困惑。所以这是我对bootstrapping的正式描述的尝试,它接近你的,但在源,目标和实现语言之间有更明确的区别,还有更多的细节:
设X是源语言(即您新发明的语言),Y是目标语言(例如汇编或机器语言),Z是另一种语言,至少有一种实现已经存在。设T : X -> Y
为翻译方案,将用X语言编写的有效程序翻译成用Y语言编写的等效程序。换句话说,对于用X编写的任何有效程序x,T(x)
应生成一个用y编写的程序。 Y,其行为与x
的定义行为等效。
现在我们要做的第一件事就是在编程语言Z中实现这个函数T.让我们调用这个实现C_0
。由于Z的实现已经存在,我们现在可以开始编译X程序。这是你的第1步,除非你似乎在第二句中改变了X和Y.
在我们这样做之后,我们现在可以再次实现T,但这次是用语言X.所以我们编写了一个等同于C_1
的程序C_0
,但是用X而不是Z编写。我们仍然在从X到Y进行编译,但是我们在X中进行编译。我们现在可以使用C_0
来应用T(C_1)
并且我们得到一个(另一个)工作X编译器。除了我们仍将X
翻译为Y
之外,这与您的步骤类似。将X翻译成自身是没有意义的,因为那只是无所事事。将Y翻译成自身会更有意义,因为Y甚至不是我们的源语言。
我们现在也可以使用T(C_1)
代替C_1
来应用C_0
,但此时这仅用于测试目的(确保编译器正常工作)。理想情况下,C_1(C_1)
的结果应与C_0(C_1)
的Y代码完全相同。一旦我们开始向X添加功能,我们可能只会在C_1
中实现这些功能,所以此时我们要停止使用C_0
,以便我们可以使用新功能。
答案 1 :(得分:0)
想象一下,您想要创建一种名为XYZPDQ的新语言。你知道C,所以你在C中编写了XYZPDQ的编译器。它有效,所以现在你可以用XYZPDQ语言编写代码并使用你在C中编写的编译器编译它,也许叫做XYZPDQc。
事实上,你非常喜欢你第二次编写编译器 - 但这次你用XYZPDQ语言编写它。您使用在C中编写的编译器(XYQPDQc程序)编译XYZPDQ编译器代码(用XYZPDQ本身编写)。结果是你可以运行的一个新程序,也许叫做XYZPDQc2。
现在您可以使用XYZPDQc2程序编译在XYZPDQ中编写的XYZPDQ编译器,因此编译器(实际上)编译自己。
此时:您已经使用了编译语言。